【发布时间】:2018-10-04 14:39:47
【问题描述】:
为了调试锁定的文件问题,我们从 .NET 进程调用 SysInternal 的 Handle64.exe 4.11(通过带有异步输出重定向的 Process.Start)。调用进程挂起Process.WaitForExit,因为 Handle64 进程没有退出(超过两个小时)。
我们转储了相应的 Handle64 进程,并在 Visual Studio 2017 调试器中对其进行了检查。它显示了两个线程(“主线程”和“ntdll.dll!TppWorkerThread”)。
主线程的调用栈:
ntdll.dll!NtWaitForSingleObject () Unknown ntdll.dll!LdrpDrainWorkQueue() Unknown ntdll.dll!RtlExitUserProcess() Unknown kernel32.dll!ExitProcessImplementation () Unknown handle64.exe!000000014000664c() Unknown handle64.exe!00000001400082a5() Unknown kernel32.dll!BaseThreadInitThunk () Unknown ntdll.dll!RtlUserThreadStart () Unknown
工作线程的调用栈:
ntdll.dll!NtWaitForSingleObject() Unknown ntdll.dll!LdrpDrainWorkQueue() Unknown ntdll.dll!LdrpInitializeThread() Unknown ntdll.dll!_LdrpInitialize() Unknown ntdll.dll!LdrInitializeThunk() Unknown
我的问题是:为什么进程会在LdrpDrainWorkQueue 中挂起?从https://stackoverflow.com/a/42789684/62838,我了解到这是正在工作的 Windows 10 并行加载程序,但为什么它会在退出进程时卡住?这可能是由于我们如何从另一个进程调用 Handle64 造成的吗?即,我们是做错了什么还是这只是 Handle64 中的一个错误?
【问题讨论】:
-
这只是 handle64 中的 1 个工作线程吗?我想更多和不同的调用堆栈。这个挂起是总是在你的系统上还是随机的?
-
我什至可以说这是不是
LoaderWorker线程的调用栈——它从不从LdrpInitializeThread调用LdrpDrainWorkQueue,因为这个线程有特殊的、非常轻的初始化 -
我能说什么 - 在调用
ExitProcess时 - 一些 DLL 被加载到另一个线程中,工作线程的调用堆栈 - 这 100% 不是加载器工作线程,但其他一些。主线程和这个仅开始执行的新线程(在非常早期的阶段)都在等待LdrpLoadCompleteEvent事件。当某些 DLL 的加载完成时,此事件设置在单个位置LdrpDropLastInProgressCount。必须是正在处理的附加胎面。这里需要更多地查看调试器。作为旁注,很容易根本不使用handle64,而是自己获取所有信息 -
@RbMm 非常感谢您的分析!根据调试器的说法,在进行转储时,Handle64.exe 中只有一个工作线程。 (可能其他线程已经退出了?)
-
它并不总是发生,到目前为止,我们在几十个电话中只看到过一次。
标签: c++ windows multithreading process