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

本文关键字:客户端 出口 挂起 偶尔 Read AnonymousPipeServerStream | 更新日期: 2023-09-27 18:18:56

我有一个主程序和一个从程序,它们通过一对匿名管道交互。

交互作用如下:

  • Master创建两个AnonymousPipeServerStream
  • 主启动客户端进程,给他。getclienthandleasstring ()
  • Master .DisposeLocalCopyOfClientHandle的两个管道
  • Master向一个管道写入内容,并从另一个管道读取内容
  • 偶尔主线程从另一个线程强制终止从线程(Process.Kill()),同时关闭两个管道对象。

在非常罕见的情况下,在从端终止时,从主端的管道读取会无限期阻塞,或者有时会阻塞(例如几分钟)。我无法在我的本地机器上重现它,但在大型集群上有时会发生这种情况。

我捕获了这种情况的转储,下面是我看到的:

阻塞主进程的堆栈跟踪(我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 ()):

这是主端句柄的!句柄的输出。

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。

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

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

  • 1 -即将调用Microsoft.Win32.UnsafeNativeMethods。ReadFile (inside BinaryReader.ReadInt32)
  • 2 -终止从进程并关闭管道句柄
  • 3 - win32管道句柄(现在关闭)被重用用于其他管道(或文件或任何)
  • 1 - Microsoft.Win32.UnsafeNativeMethods。ReadFile使用旧句柄开始读取,该句柄现在指向其他对象,并阻塞。

修复:

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

道德:

不要在使用句柄时关闭它们