c++ 迷你转储写入转储()挂起

50few1ms  于 2023-01-06  发布在  其他
关注(0)|答案(1)|浏览(175)

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

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

ruarlubt

ruarlubt1#

一般来说,MiniDumpWriteDump执行两个操作:
1.挂起目标进程中的所有线程。
1.完成后,转储目标进程的状态。
第一步是挂起每个线程,不管它当前在做什么。如果它碰巧独占访问一个共享资源,它将无限期地占用它。只有一种单一可靠的方法来调用MiniDumpWriteDump,如文档所示:
MiniDumpWriteDump应该尽可能从单独的进程调用,而不是从正在转储的目标进程内调用。当目标进程已经不稳定时尤其如此。例如,如果它刚刚崩溃。加载程序死锁是从目标进程内调用MiniDumpWriteDump的许多潜在副作用之一。
文档没有列出这个API可能导致死锁的所有方式。在您的例子中,您似乎挂起了一个正在从堆分配内存的线程。默认情况下,堆是同步的。随着MiniDumpWriteDump的继续,它 * 也 * 试图分配堆内存。为此,它请求堆同步对象。但该对象从未被释放。因为它只是挂起了拥有对它的独占访问权的线程。
同样,这只是这个API死锁的一种方式,当从同一个进程中调用它时,它被指示转储。有很多很多其他的机会发生这种情况。
解决方案:将其放在外部进程中。

相关问题