3

我想做一个进程外异常处理程序,并且我创建了一个看门狗进程,它在子进程引发异常时进行专门的异常处理。我已经通过 events 成功调用了 watchdog 进程。我面临的问题是尝试将异常信息指针传递给另一个进程。

我在这里登陆了传递一个指向由 exec() 生成的进程的指针,并知道在共享内存中传递指针有这个问题:

“如果你使用共享内存,你不能传递指针。指针将包含虚拟地址,这与一个进程不同。你必须交换偏移值,基于共享内存区域的开始。

如果您不使用共享内存,则无法交换任何类型的指针:其他进程将无法访问您进程的内存。”

现在我该如何克服呢?

过程1:

    struct mytest
    {
      _EXCEPTION_POINTERS * except ;
      DWORD ThreadId ;
      DWORD ProcessId ;
    }

    OpenFileMapping ( ) ;

    void * pBuf = MapViewOfFile ( ) ;

    mytest passdata ;

    CopyMemory ( pBuf , &passdata , sizeof ( passdata ) ) ;

    UnMapView ( ) ;

    CloseHandle ( ) ;

(例如)过程 2:

    cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;

会崩溃。我理解这是因为虚拟地址是特定于进程的。但是在这种情况下如何将异常信息传递给不同的进程并编写一个小型转储?

PS:我什至尝试单独传递 PEXCEPTION_RECORD 结构,但不起作用。

4

2 回答 2

3

我将把它放在一起作为答案,虽然它确实应该是对汉斯的回答(以及那里的评论)的评论,但似乎有必要进行一些解释:

问题中发布的代码正确地将结构的值传递struct mytest到共享内存中。

第二个代码片段:

(例如)过程 2:

cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;

虽然显示了一个误解:虽然您可以读取指针的值,但passdata.except在进程 2 中这只是一个任意的 32/64 位值,它不是一个有效的指针。

可以将 this 传递给MiniDumpWriteDump,此函数将在目标进程(proc 1)的上下文中评估此指针值。但是你不能在过程#2 中取消引用它。

Hans 的示例给出了解决方案,如果您需要ExeptionCode进程#2 中的值,那么您需要取消引用 proc#1 中的指针并将该值放入您写入共享内存的数据中。

于 2013-04-23T12:02:13.117 回答
2

对,你不能在另一个进程中取消引用指针,它只在崩溃的进程中有效。仅传递给 MiniDumpWriteDump()、MINIDUMP_EXCEPTION_INFORMATION.ExceptionPointers 字段就足够了。从技术上讲,您可以使用 ReadProcessMemory() 但对于崩溃的进程这样做是不必要的风险。简单的解决方案是在结构中添加一个额外的字段,用于存储异常代码并由异常过滤器编写。

mytest passdata ;
passdata.except = ExceptionInfo;
// Note: added field
passdata.ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
passdata.ThreadId = GetCurrentThreadId();
// etc..

还要避免调用 OpenFileMapping 和 MapViewOfFile 之类的 winapi 函数,风险太大。当程序由于进程堆的堆损坏而崩溃时,它们往往会死锁。崩溃和死锁的常见原因是堆锁仍然被持有。只需在程序初始化时执行此操作。您也不需要费心清理,当您的看门狗进程在进行小型转储后终止崩溃的进程时,Windows 会处理它。

于 2013-04-22T14:24:15.833 回答