有没有办法知道另一个进程中抛出异常的线程ID?

发布于 2024-10-01 06:23:47 字数 1193 浏览 12 评论 0原文

我正在尝试使用 MiniDumpWriteDump() API 从另一个进程 A 转储崩溃的进程 B。我这样做是因为 MSDN 是这么说的:

应该调用MiniDumpWriteDump 如果有的话,来自一个单独的过程 可能,而不是从内部 目标进程正在转储。

MiniDumpWriteDump() 的定义如下:

BOOL WINAPI MiniDumpWriteDump(
  __in  HANDLE hProcess,
  __in  DWORD ProcessId,
  __in  HANDLE hFile,
  __in  MINIDUMP_TYPE DumpType,
  __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

特别是,ExceptionParam 的类型为 PMINIDUMP_EXCEPTION_INFORMATION,其定义如下:

typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
  DWORD               ThreadId;
  PEXCEPTION_POINTERS ExceptionPointers;
  BOOL                ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

现在我想知道如何准备以下 2 个参数:

ThreadId 抛出异常的线程的标识符。

异常指针 指向 EXCEPTION_POINTERS 结构的指针,指定异常的计算机独立描述以及异常发生时的处理器上下文。

在进程 A 中运行时,如何获取进程 B 中的错误线程 ID 和异常指针?

谢谢。

I am trying to use MiniDumpWriteDump() API to dump a crashed process B from another process A. I am doing this because MSDN said so:

MiniDumpWriteDump should be called
from a separate process if at all
possible, rather than from within the
target process being dumped.

The MiniDumpWriteDump() is defined as this:

BOOL WINAPI MiniDumpWriteDump(
  __in  HANDLE hProcess,
  __in  DWORD ProcessId,
  __in  HANDLE hFile,
  __in  MINIDUMP_TYPE DumpType,
  __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

Especially, the ExceptionParam is of type PMINIDUMP_EXCEPTION_INFORMATION, which is defined as below:

typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
  DWORD               ThreadId;
  PEXCEPTION_POINTERS ExceptionPointers;
  BOOL                ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

Now I am wondering how to prepare the following 2 parameters:

ThreadId
The identifier of the thread throwing the exception.

ExceptionPointers
A pointer to an EXCEPTION_POINTERS structure specifying a computer-independent description of the exception and the processor context at the time of the exception.

How could I get the faulting thread id and exception pointers in process B while running in process A?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

罗罗贝儿 2024-10-08 06:23:47

指向 MINIDUMP_EXCEPTION_INFORMATION 结构的指针,描述导致生成小型转储的客户端异常。如果该参数值为NULL,则minidump文件中不包含任何异常信息。

尽管参数被标记为 __in 而不是 __in_opt,但您确实可以在此处传递 NULL。要首先从目标进程获取该信息,您的进程无论如何都必须对其进行调试。

进程 A 如何以及何时知道进程 B 的小型转储?如果 A 确实正在调试 B,则当 WaitForDebugEvent 返回并带有 EXCEPTION_DEBUG_EVENT 时,该信息在 info 结构中可用。

如果 A 没有调试 B,那么 B 可能会通过某种 IPC 机制告诉 A“嘿,我崩溃了,进行小型转储”。在这种情况下,B 可以自己进行转储,或者通过相同的 IPC 机制将异常信息传递给 A。不过,这也是有问题的,因为在崩溃过程中调用 MiniDumpWriteDump 也是有问题的,如果事情发生了,事情就会发生可能已经爆炸的事情可能就是你需要告诉 A 的事情。

另一种可能让 A 转储 B 的机制是 A 作为 JIT 调试器安装,在这种情况下,A 将调试 B,并且您可以使用调试 API 来获取异常信息。

如果 A 只是定期获取 B 的小型转储,则不一定会出现任何异常,因此在这种情况下您可以只传递 NULL。

请注意,如果您打算做类似的事情,

WaitForSingleObject(handleToProcessB, INFINITE);
MiniDumpWriteDump(handleToProcessB, ...)

那么这是行不通的。操作系统保留了很少的东西,主要是进程的退出代码,而不是虚拟地址空间和进行小型转储所需的堆栈。

A pointer to a MINIDUMP_EXCEPTION_INFORMATION structure describing the client exception that caused the minidump to be generated. If the value of this parameter is NULL, no exception information is included in the minidump file.

Despite the fact that the paramter is marked __in and not __in_opt you can indeed pass NULL here. To get that information in the first place from the target process your process would have to be debugging it anyway.

How and when does process A known to take a minidump of process B? If A is indeed debugging B, when WaitForDebugEvent returns with an EXCEPTION_DEBUG_EVENT, the information is available in the info structure.

If A isn't debugging B, then perhaps B is telling A through some IPC mechanism "Hey I'm crashing, take a minidump". In this case either B could take the dump itself or pass the exception information through the same IPC mechansim to A. Again though, this is problematic for the same reasons calling MiniDumpWriteDump in the crashing process is problematic, if things are blowing up, the thing that might have blown up may be what you need to tell A about it.

The other mechanism that might have A take a dump for B is A is installed as the JIT debugger, in which case, A will be debugging B and you can use the debugging APIs to get the exception information.

If A is just periodically taking minidumps of B, then there won't necessarily be any exceptions, so you can just pass NULL in this case.

Note that if you're intending on doing something like

WaitForSingleObject(handleToProcessB, INFINITE);
MiniDumpWriteDump(handleToProcessB, ...)

that this will not work. The OS keeps around a very few things, mainly the exit code for the process, not the virtual address space and the stacks which you need to take a minidump.

不乱于心 2024-10-08 06:23:47

要针对特定​​进程名称的给定异常创建自动转储,我的建议是使用 DebugDiag 或 AdPlus。这些是外部(并且免费!)软件,您可以配置它们来执行此操作。

如果你真的想自己写转储,你可以在进程 B 中完成:MSDN 警告你这不是一个好主意,因为像内存不足、堆栈溢出或堆栈损坏(列表并不详尽)等令人讨厌的错误会发生当然会使用内存和堆栈,因此您最终可能根本没有转储(并且会导致非常严重的进程崩溃)。根据我的经验,这种情况非常罕见(我曾经开发过压力很大的分布式 C++ 软件)。
对于其他例外,应该没问题。在这种情况下,您可以使用异常转换器(请参阅 _set_se_translator)或向量异常处理程序(请参阅 AddVectoredContinueHandler)或函数 GetExceptionInformation() 来获取 EXCEPTION_RECORD 结构(可能还有其他我不知道的方法)。

在进程 B 发生异常后从进程 A 创建转储意味着您必须复制有关异常的所有信息,并警告进程 A 它必须转储带有此异常的内容。这将消耗内存和堆栈,因此您将受到与之前解释的相同的限制。

希望这会有所帮助

To have an automatic dump created on a given exception on a specific process name, my advise would be to use DebugDiag or AdPlus. Those are external (and free !) software that you can configure to do so.

If you really want to write the dump by yourself, you can do it in process B : MSDN warn you that is not a good idea, because nasty errors like out of memory, stack overflow, or stack corruption (list is not exhaustive) will certainly use memory and stack, and so you may ends up with no dump at all (and a very bad process crash). From my experience, this is pretty rare (I used to work on a very stressed distributed C++ software).
For others exception, it should be ok. In that case, you can use an exception translator (see _set_se_translator) or a vectored exception handler (see AddVectoredContinueHandler) or the function GetExceptionInformation() to get the EXCEPTION_RECORD structure (there may be others ways that I'm not aware of).

Creating the dump from process A after an exception in process B means that you have to copy all informations about the exception, and warn the process A that it has to dump something with this exception. This will consume memory and stack, and so you will have the same limitation than explained before.

Hope that will help

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文