简体   繁体   中英

NamedPipeClientStream.Connect() throws System.IO.FileNotFoundException: Unable to find the specified file

Can anyone please tell me why NamedPipeClientStream.Connect() would throw a System.IO.FileNotFoundException exception (Unable to find the specified file)? I thought the Connect() method will just block forever rather than throwing an exception.

Thank you in advance!

NamedPipeClientStream.Connect() is just managed wrapper over WaitNamedPipe and CreateFile kernel method.

More here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365800(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx

The managed part looks like (simplified):

public void Connect(int timeout = -1) {
  int tickCount = Environment.TickCount;
  int elapsed = 0;
  SafePipeHandle safePipeHandle;
  while (true) {
    if (!WaitNamedPipe(normalizedPipePath, timeout - elapsed)) {
      int lastWin32Error = Marshal.GetLastWin32Error();
      if (lastWin32Error != FILE_NOT_FOUND && lastWin32Error != SUCCESS) {
        ThrowWinIOError(lastWin32Error, string.Empty);
      }
    }
    if (timeout != -1 && (elapsed = Environment.TickCount - tickCount) >= timeout) {
      throw new TimeoutException();
    }

    safePipeHandle = CreateFile(normalizedPipePath, m_access, FileShare.None, null, FileMode.Open, num, null);
    if (!safePipeHandle.IsInvalid) {
      // success
      return;
    }
    int lastWin32Error2 = Marshal.GetLastWin32Error();
    if (lastWin32Error2 == PIPE_BUSY) {
      continue;
    }
    ThrowWinIOError(lastWin32Error2, string.Empty);
  }
}

So it invokes WaitNamedPipe which returns immediatelly if pipe doesn't exist and managed code does the retry (it retries indefinetly if no timeout is specified). Tricky part is that CreateFile does no handling of FILE_NOT_FOUND error (it handles just PIPE_BUSY error) - I suspect this is where you can run into racial condition.

IE: WaitNamedPipe returns ok, but before CreateFile is hit the pipe changed (went back to void after hibernation ?) and CreateFile throws exception you're seeing.

Workaround should be relatively simple - wrap Connect method to retry on FILE_NOT_FOUND IOException .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM