I wanted to do a out-of-process exception handler and i had created a watch-dog process which does dedicated exception handling when child process raises exception. I had successfully invoked the watchdog process through events . The problem i am facing is while trying to pass the exception information pointers to the other process .
I landed here Passing a pointer to process spawned with exec() and came to know that passing pointers in shared memory has this issue :
"If you use shared memory, you can't pass the pointer. The pointer will contain the virtual address, which is different from one process to another. You have to exchange offset values, based on the start of the shared memory area.
If you don't use shared memory, you can't exchange pointers of any kind: The other process won't be able to access the memory of your process."
Now how can i overcome this ?
Process 1 :
struct mytest
{
_EXCEPTION_POINTERS * except ;
DWORD ThreadId ;
DWORD ProcessId ;
}
OpenFileMapping ( ) ;
void * pBuf = MapViewOfFile ( ) ;
mytest passdata ;
CopyMemory ( pBuf , &passdata , sizeof ( passdata ) ) ;
UnMapView ( ) ;
CloseHandle ( ) ;
(For ex)Process 2 :
cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;
would crash . I understand this is because virtual address is process specific . But in this case how to pass exception information to different process and write a minidump ??
P.S : I even tried passing PEXCEPTION_RECORD structures seperately but does not work .
Right, you cannot dereference the pointer in another process, it is only valid in the crashed process. It is only good enough to pass to MiniDumpWriteDump(), MINIDUMP_EXCEPTION_INFORMATION.ExceptionPointers field. Technically you could use ReadProcessMemory() but doing so for a crashed process is unnecessarily risky. The simple solution is to add an extra field to your structure that stores the exception code and written by your exception filter.
mytest passdata ;
passdata.except = ExceptionInfo;
// Note: added field
passdata.ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
passdata.ThreadId = GetCurrentThreadId();
// etc..
Also avoid calling winapi functions like OpenFileMapping and MapViewOfFile, it is too risky. They tend to deadlock when the program crashed due to heap corruption of the process heap. A common reason to crash and a deadlock because the heap lock is still held. Just do this at program initialization. You don't need to bother cleaning up either, Windows takes care of it when your watchdog process terminates the crashed process after taking the minidump.
I will put this together as an answer, although it really should be a comment to Hans's answer (and the comments there) but it seems some explanation is necessary:
The code posted in the question correctly passes the value(s) of the struct mytest
structure into shared memory.
The second code snippet:
(For ex)Process 2 :
cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;
Shows a misunderstanding though: While you can read the value of the pointer passdata.except
, in process 2 this is just an arbitrary 32/64 bit value, it is not a valid pointer.
You can pass this to MiniDumpWriteDump
, this function will eveluate this pointer value in the context of the target process (proc 1). But you cannot dereference it in process #2.
Hans's example gives the solution, iff you need the value of ExeptionCode
in process #2, then you need to dereference the pointer in proc#1 and put the value into the data you write to shared memory.
来源:https://stackoverflow.com/questions/16147753/trouble-passing-exception-pointers-using-filemapping