AnonymousPipeServerStream.Read() иногда зависает при выходе клиента

У меня есть ведущая и ведомая программы, которые взаимодействуют через пару анонимных труб.

Взаимодействие выглядит так:

  • Ведущий создает два AnonymousPipeServerStream'а
  • Ведущий запускает клиентский процесс, передавая ему их .GetClientHandleAsString()
  • Ведущий .DisposeLocalCopyOfClientHandle'ы обеих труб
  • Ведущий пишет материал в одну трубу и читает материал из другой
  • Иногда ведущий принудительно завершает ведомого из другого потока (Process.Kill()), А ТАКЖЕ закрывает оба объекта труб.

В очень редких случаях, после завершения работы ведомого, чтение из трубы на стороне ведущего блокируется на неопределенное время - а иногда и надолго (например, на несколько минут). Я не могу воспроизвести это на своей локальной машине, но это происходит время от времени на большом кластере.

Я сделал дамп этой ситуации, и вот что я увидел:

Stacktrace заблокированного мастера (я на 100% уверен, что в этот момент клиентский процесс уже завершен):

000000000c83e488 000000007700fdba [NDirectMethodFrameStandalone: 000000000c83e488] Microsoft.Win32.UnsafeNativeMethods.ReadFile(Microsoft.Win32.SafeHandles.SafePipeHandle, Byte*, Int32, Int32 ByRef, IntPtr)
000000000c83e430 000007feeab32820 DomainBoundILStubClass.IL_STUB_PInvoke(Microsoft.Win32.SafeHandles.SafePipeHandle, Byte*, Int32, Int32 ByRef, IntPtr)*** WARNING: Unable to verify checksum for System.Core.ni.dll

000000000c83e540 000007feeac14574 System.IO.Pipes.PipeStream.ReadFileNative(Microsoft.Win32.SafeHandles.SafePipeHandle, Byte[], Int32, Int32, System.Threading.NativeOverlapped*, Int32 ByRef)
000000000c83e5a0 000007feeac14a23 System.IO.Pipes.PipeStream.ReadCore(Byte[], Int32, Int32)
000000000c83e610 000007fef0169d8f System.IO.BinaryReader.FillBuffer(Int32)
000000000c83e650 000007fef0169c8a System.IO.BinaryReader.ReadInt32()

Я также посмотрел на объект AnonymousPipeServerStream, который блокируется, и на его состояние и хэндл.

Он имеет:

  • m_state = 4 (т.е. закрыт)
  • m_clientHandle - закрытый хэндл (согласно SafeHandle._state и выводу !handle)
  • m_handle - открытый хэндл, с _state = 6 (т.е. т.е. НЕ закрыт, хотя объект Pipe закрыт и, согласно декомпиляции, он должен был вызвать m_handle.Dispose()):

Вот вывод !handle для ручки на стороне мастера.

0:000> !handle 1850 ff
Handle 0000000000001850
  Type          File
  Attributes    0
  GrantedAccess 0x120189:
         ReadControl,Synch
         Read/List,ReadEA,ReadAttr,WriteAttr
  HandleCount   2
  PointerCount  5
  No object specific information available

Меня немного беспокоит, что HandleCount равен 2, а PointerCount равен 5.

Есть идеи, что могло пойти не так? Почему ручка чтения со стороны мастера не была закрыта, когда я закрыл трубу? Почему труба не была разорвана, несмотря на завершение работы клиента и несмотря на то, что я вызвал DisposeLocalCopyOfClientHandle?

Что я могу сделать, чтобы хотя бы обойти это? Может быть, просто сделать Thread.Interrupt на читающем потоке?...

14
задан jkff 25 December 2011 в 09:26
поделиться