MiniDumpWriteDump() 挂起

MiniDumpWriteDump() hangs

如果堆 allocation/deallocation/reallocation 在另一个线程中进行,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

您知道这种情况的简单解决方法吗?我可以看到一种解决方法,即向我的应用程序中的所有其他线程注入检查,以查看是否请求了核心转储,然后在没有获得互斥体的地方暂停。但这是一个很大的变化,而且应用程序的一些线程不受我的控制,因为它们是由我内部使用的库启动的。

一般来说,MiniDumpWriteDump 执行两个操作:

  1. 暂停目标进程中的所有线程。
  2. 完成后,转储目标进程的状态。

第一步挂起每个线程,不管它当前在做什么。如果它碰巧持有对共享资源的独占访问权,它将无限期地持有它。只有单一可靠调用MiniDumpWriteDump的方法,如文档所述:

MiniDumpWriteDump should be called from a separate process if at all possible, rather than from within the target process being dumped. This is especially true when the target process is already not stable. For example, if it just crashed. A loader deadlock is one of many potential side effects of calling MiniDumpWriteDump from within the target process.

文档没有列出此 API 可能导致死锁的所有可能方式。在您的情况下,您似乎暂停了一个正在从堆分配内存的线程。默认情况下,堆是同步的。随着 MiniDumpWriteDump 的进行,它 尝试分配堆内存。为此,它请求堆同步对象。但是它永远不会被释放,因为它只是挂起线程以独占访问它。

同样,这只是一个 单一 方法,当从同一进程中调用时,它被指示转储,这个 API 可能会死锁。有很多很多其他机会可以实现这一点。

解决方法:放在外部进程中。