AnonymousPipeServerStream.Read()偶尔会在客户端出口挂起

jkf*_*kff 14 .net c# windows debugging pipe

我有一个主程序和一个从程序通过一对匿名管道进行交互.

交互看起来像这样:

  • Master创建了两个AnonymousPipeServerStream
  • Master启动客户端进程,给他们.GetClientHandleAsString()
  • 掌握.DisposeLocalCopyOfClientHandle的两个管道
  • Master将东西写入一个管道并从另一个管道中读取东西
  • 偶尔master会从另一个线程强制终止slave(Process.Kill()),并且还关闭两个管道对象.

在非常罕见的情况下,在从机终止时,从主机侧的管道读取无限期地阻塞 - 或者有时肯定地(例如几分钟).我无法在本地计算机上重现它,但它在大型群集上不时发生.

我抓住了这种情况的转储,这就是我所看到的:

被阻止的master的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()
Run Code Online (Sandbox Code Playgroud)

我还查看了阻塞的AnonymousPipeServerStream对象,以及它的状态和句柄.

它有:

  • m_state = 4(即关闭)
  • m_clientHandle是一个封闭的句柄(根据SafeHandle._state和!handle的输出)
  • m_handle是一个打开的句柄,_state = 6(即NOT关闭,即使Pipe对象已关闭,根据反编译,它应该调用m_handle.Dispose()):

这是主侧手柄的!句柄输出.

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
Run Code Online (Sandbox Code Playgroud)

我有点担心HandleCount是2而PointerCount是5.

什么想法可能会出错?当我关闭管道时,为什么读取手柄的主控端没有关闭?尽管客户端终止了,尽管事实上我调用了DisposeLocalCopyOfClientHandle,为什么管道没有损坏?

我能做些什么来至少解决这个问题?也许只是在阅读线程上做Thread.Interrupt?..

arx*_*arx 2

主进程中可能的事件顺序,前面是线程号:

  • 1 - 将要调用 Microsoft.Win32.UnsafeNativeMethods.ReadFile (在 BinaryReader.ReadInt32 内部)
  • 2 - 终止从属进程并关闭管道句柄
  • 3 - win32 管道句柄(现已关闭)被其他管道(或文件或其他)重用
  • 1 - Microsoft.Win32.UnsafeNativeMethods.ReadFile 开始使用现在引用某个其他对象的旧句柄进行读取,然后阻塞。

使固定:

终止线程 2 中的从进程,但不关闭句柄。这将导致线程 1 中的任何读取终止,然后关闭线程 1 中的管道句柄。

道德:

当您仍在使用手柄时,请勿关闭它们。