How to determine if a custom terminate () handler is installed?

My code compiled as a Windows DLL with Visual C ++. I want to register rare cases when terminate() is called, so I set the terminate() handler to the library initialization function, and the latter is called by the user code before using my library. My handler writes to the log and calls abort() , emulating the default behavior of terminate() .

The problem is that the user code can also be written in C ++ and use the same version of C ++ execution and thus share the terminate() handler with my library. This code may also want to modify the terminate() handler for logging. So they will call set_terminate() , then load and initialize my library, and my library will also call set_terminate() and override their terminate() handler, and it will be very difficult to detect, because the terminate() handler is the last thing they will check , I believe.

So, I want the following. Inside the library initialization function, I retrieve the current terminate() handler , find if it is standard, and if it is non-standard, I will save its address and later (if necessary) my terminate() handler will write to the log and then redirect the call to this user terminate() handler.

Is it possible to determine whether the terminate() handler is currently installed, by default or custom?

+4
source share
2 answers

Do this via RAII as follows:

 class terminate_scope { public: terminate_function _prev; terminate_scope(terminate_function f = NULL){ _prev = set_terminate(f); } ~terminate_scope(){ set_terminate(_prev); } }; 

For use:

 void MyFunctionWantsOwnTerminateHandler(){ terminate_scope termhandler(&OwnTerminateHandler); // terminate handler now set // All my code will use that terminate handler // On end of scope, previous terminate handler will be restored automatically } 

You may have a chain of handlers to complete the previous one if you are absolutely sure what you need.

+2
source

MSDN vaguely says that

If the previous function was not installed, the return value ( set_terminate ) can be used to restore the default behavior; this value may be NULL;

and the same for _get_terminate . I believe this is not very useful, because if the return value is not NULL, there is still no guarantee that it is a valid terminate handler. One possible solution is to use GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS to find out if the address returned by set_terminate valid address in any module.

0
source

Source: https://habr.com/ru/post/1392631/


All Articles