Trouble passing _EXCEPTION_POINTERS * using FileMapping
Asked Answered
E

2

3

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 .

Errand answered 22/4, 2013 at 13:1 Comment(0)
B
2

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.

Beguin answered 22/4, 2013 at 14:24 Comment(6)
Thans @Hans Passant ! I have only one clarification . Have you tried passing MINIDUMP_EXCEPTION_INFORMATION.ExceptionPointers field . Will it be readable in the child process ??Errand
Yes, that's why the field is there. No, it isn't readable in a "client process". Or the watchdog process as I explained. It is used by MiniDumpWriteDump and gets recorded in the minidump file. So when you open the minidump in a debugger, it can show you where the exception occurred. The debugger doesn't have a problem using the pointer since it is debugging the process that owns the pointer.Beguin
Then how and what are the steps needed to call a MiniDumpWriteDump in a watch-dog ?Errand
That's an entirely different question. Be sure to click the Ask Question button if the existing answers do not help. Use google or the Search box at the upper right corner of this page.Beguin
Thanks again for the enlightenment !Errand
Sorry to revoke this , but i read your comments here : #10672630 . You have clearly stated that waking a watch-dog and calling MiniDumpWriteDump in Watchdog is the right way ? And i am sure you are aware that MiniDumpWriteDump needs atleast one parameter as a pointer ( even Minidump_exception_information.exceptionPointers field ) . so how did you get through this ? I am curious because you have commented which implies you would have very well implemented . Sorry to bother!Errand
U
3

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.

Unpleasantness answered 23/4, 2013 at 12:2 Comment(2)
Cool , Thanks @Martin Ba . Will proceed as you guide .Errand
Finally done with it . If someone in future faced problem with Failing to Write MiniDump Check your process security access and rights .Errand
B
2

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.

Beguin answered 22/4, 2013 at 14:24 Comment(6)
Thans @Hans Passant ! I have only one clarification . Have you tried passing MINIDUMP_EXCEPTION_INFORMATION.ExceptionPointers field . Will it be readable in the child process ??Errand
Yes, that's why the field is there. No, it isn't readable in a "client process". Or the watchdog process as I explained. It is used by MiniDumpWriteDump and gets recorded in the minidump file. So when you open the minidump in a debugger, it can show you where the exception occurred. The debugger doesn't have a problem using the pointer since it is debugging the process that owns the pointer.Beguin
Then how and what are the steps needed to call a MiniDumpWriteDump in a watch-dog ?Errand
That's an entirely different question. Be sure to click the Ask Question button if the existing answers do not help. Use google or the Search box at the upper right corner of this page.Beguin
Thanks again for the enlightenment !Errand
Sorry to revoke this , but i read your comments here : #10672630 . You have clearly stated that waking a watch-dog and calling MiniDumpWriteDump in Watchdog is the right way ? And i am sure you are aware that MiniDumpWriteDump needs atleast one parameter as a pointer ( even Minidump_exception_information.exceptionPointers field ) . so how did you get through this ? I am curious because you have commented which implies you would have very well implemented . Sorry to bother!Errand

© 2022 - 2024 — McMap. All rights reserved.