ckr*_*mer 8 .net clr f# garbage-collection tail-recursion
我正在尝试使用Windows服务调试生产问题,一旦多个并发连接处于活动状态,该服务就会迅速崩溃.通过核心转储和DebugDiag的神奇之处,我发现有一个挂起的GC操作,直到几个Preemptive GC禁用的线程完成了他们的工作才能启动.
以下是来自WinDbg的示例线程转储,显示了有问题的线程:
26 6e 1444 00..440 8009222 Disabled 00..200:00..f88 00..7a0 0 MTA (Threadpool Completion Port)
27 c1 1a0c 00..fe0 8009222 Disabled 00..e90:00..f88 00..7a0 0 MTA (Threadpool Completion Port)
28 b5 17bc 00..6f0 8009222 Disabled 00..268:00..f88 00..7a0 0 MTA (Threadpool Completion Port)
29 89 1f1c 00..ab0 8009222 Disabled 00..a30:00..f88 00..7a0 0 MTA (Threadpool Completion Port)
30 ac 2340 00..f70 8009220 Disabled 00..d00:00..d08 00..7a0 1 MTA (GC) (Threadpool Completion Port)
31 88 1b64 00..fd0 8009220 Enabled 00..b28:00..b48 00..7a0 0 MTA (Threadpool Completion Port)
Run Code Online (Sandbox Code Playgroud)
所以在这里你可以看到几个具有抢占GC禁用的线程(线程26,27,28,29)和一个(线程30)等待这些线程执行GC的线程.
我的Google-fu引导我访问这篇博文,其中描述了类似问题,只是在我的情况下,没有涉及XML.它给了我足够的信息来知道在哪里挖掘,最后我发现禁用抢先GC的线程的一个常见功能是堆栈跟踪,如上图所示:
ntdll!NtWaitForSingleObject+a
ntdll!RtlpWaitOnCriticalSection+e8
ntdll!RtlEnterCriticalSection+d1
ntdll!RtlpLookupDynamicFunctionEntry+58
ntdll!RtlLookupFunctionEntry+a3
clr!JIT_TailCall+db
...
Run Code Online (Sandbox Code Playgroud)
DebugDiag还警告我关于CriticalSection,并且它恰好是带有的线程JIT_TailCall也是唯一的线程RtlEnterCriticalSection
所以我的问题是:它实际上.tail是导致这种僵局的指令吗?如果是这样的话:我能做些什么呢?
我可以在我的.fsproj文件上禁用尾调用,但看起来至少其中一个是来自FSharp.Core.dll反编译器的一些探测器似乎确认了.tail指令的存在.所以我不知道chaning项目配置将删除所有.tail指令.
有没有人以前处理过这样的事情?
更新:一些可能有用的信息.
以下是!locks此转储的输出:
!locks
CritSec +401680 at 0000000000401680
WaiterWoken No
LockCount 0
RecursionCount 1
OwningThread 2340
EntryCount 0
ContentionCount bf
*** Locked
Scanned 1657 critical sections
Run Code Online (Sandbox Code Playgroud)
线程2340是已经启动GC的线程(上面包括的部分列表I中的线程30).
并且!syncblk只显示ZooKeeper客户端拥有的项目(虽然令人讨厌,但没有涉及任何阻止GC启动的堆栈)
!syncblk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
11 0000000019721a38 1 1 0000000019766e20 638 7 0000000000fb2950 System.Collections.Generic.LinkedList`1[[ZooKeeperNet.Packet, ZooKeeperNet]]
Waiting threads:
18 0000000019721c68 1 1 000000001ae71420 8ac 13 00000000012defc8 System.Collections.Generic.LinkedList`1[[ZooKeeperNet.Packet, ZooKeeperNet]]
Waiting threads:
-----------------------------
Total 64
CCW 0
RCW 0
ComClassFactory 0
Free 5
Run Code Online (Sandbox Code Playgroud)
我怀疑尾调用是问题所在(否则,我怀疑更多的 F# 用户会遇到这个问题)。从调用堆栈来看,您的代码似乎正在等待关键部分,这似乎更有可能是问题的根源...知道您的代码可能依赖什么同步原语吗?