Ser*_*tch 3 c++ winapi coredump deadlock dbghelp
如果堆分配/释放/重新分配正在另一个线程中进行,DbgHelp 库的 MiniDumpWriteDump() 将挂起。下面是调用堆栈:DbgHelp 暂停其他线程,然后无限期地等待这些线程获得的互斥体。
ntdll.dll!NtWaitForAlertByThreadId() Unknown
ntdll.dll!RtlpWaitOnAddressWithTimeout() Unknown
ntdll.dll!RtlpWaitOnAddress() Unknown
ntdll.dll!RtlpWaitOnCriticalSection() Unknown
ntdll.dll!RtlpEnterCriticalSectionContended() Unknown
ntdll.dll!RtlEnterCriticalSection() Unknown
ntdll.dll!RtlpReAllocateHeap() Unknown
ntdll.dll!RtlpReAllocateHeapInternal() Unknown
ntdll.dll!RtlReAllocateHeap() Unknown
ntdll.dll!LdrpSetAlternateResourceModuleHandle() Unknown
ntdll.dll!LdrResGetRCConfig() Unknown
ntdll.dll!LdrpResSearchResourceMappedFile() Unknown
ntdll.dll!LdrResSearchResource() Unknown
KernelBase.dll!FindVersionResourceSafe() Unknown
> KernelBase.dll!GetFileVersionInfoSizeExW() Unknown
dbgcore.dll!Win32LiveSystemProvider::GetImageVersionInfo(void *,unsigned short const *,unsigned __int64,struct tagVS_FIXEDFILEINFO *) Unknown
dbgcore.dll!GenAllocateModuleObject(struct _MINIDUMP_STATE *,struct _INTERNAL_PROCESS *,unsigned short *,unsigned __int64,unsigned long,struct _INTERNAL_MODULE * *) Unknown
dbgcore.dll!GenGetProcessInfo(unsigned long,struct _MINIDUMP_STATE *,struct _INTERNAL_PROCESS * *,struct _LIST_ENTRY *) Unknown
dbgcore.dll!MiniDumpProvideDump() Unknown
dbgcore.dll!MiniDumpWriteDump() Unknown
Run Code Online (Sandbox Code Playgroud)
您知道解决这种情况的简单方法吗?我可以看到一种解决方法,即向应用程序中的所有其他线程注入检查,以查看是否请求核心转储,然后在未获取互斥锁的位置暂停。但这是一个很大的变化,而且应用程序的一些线程超出了我的控制范围,因为它们是由我用于内部使用的库启动的。
一般来说,MiniDumpWriteDump执行两个操作:
第一步挂起每个线程,无论它当前正在做什么。如果它碰巧拥有对共享资源的独占访问权,它将无限期地保留它。只有一种可靠的方法来调用MiniDumpWriteDump,如文档所示:
MiniDumpWriteDump如果可能的话,应该从单独的进程调用,而不是从正在转储的目标进程内调用。当目标进程已经不稳定时尤其如此。例如,如果它刚刚崩溃了。加载程序死锁是从目标进程内调用 MiniDumpWriteDump 的许多潜在副作用之一。
该文档并未列出此 API 可能导致死锁的所有可能方式。在您的情况下,您似乎暂停了一个正在从堆分配内存的线程。默认情况下,堆是同步的。接下来MiniDumpWriteDump,它还尝试分配堆内存。为此,它请求堆同步对象。但它永远不会被释放,因为它只是暂停了对其拥有独占访问权限的线程。
同样,这只是此 API 可能陷入死锁的一种方式,当从指示转储的同一进程中调用时。有很多很多其他的机会可以实现这一点。
解决方案:将其放入外部进程中。