1

如果堆分配/解除分配/重新分配正在另一个线程中进行,则 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

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

4

1 回答 1

3

从广义上讲,MiniDumpWriteDump执行两个操作:

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

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

MiniDumpWriteDump如果可能的话,应该从一个单独的进程中调用,而不是从被转储的目标进程中调用。当目标进程已经不稳定时尤其如此。例如,如果它刚刚崩溃。加载程序死锁是从目标进程中调用 MiniDumpWriteDump 的许多潜在副作用之一。

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

同样,这只是该 API 死锁的一种方式,当从指示转储的同一进程中调用时。发生这种情况的机会很多很多。

解决方案:将其放在外部进程中。

于 2020-06-29T07:27:46.903 回答