Question

I want to do something more useful with assert than just aborting, that includes flushing some open files, and printing the stack trace.

I read a few articles on assert such as Assertions by Andrei Alexandrescu which talks about how to implement assertions. However I want to replace the assert handler by my own even in third party libraries which are used by my program. I understand most (but not all) compilers (gcc, MSVC, clang) & libraries (Qt,boost) which I use has options to set user defined assert handler. However at present I am not interested to have Abort,Retry,Ignore feature for the assert, and so not looking to my code in compiler/library specific assert handler.

As I understand, assert calls abort which sends SIGABRT signal, can I trap this signal and do the useful tasks?

Était-ce utile?

La solution

How about hijacking assert() with your own implementation? On Unix systems you can use the LD_PRELOAD trick to hijack __assert_fail (assert() itself is just a macro which calls the later one).

Another possibility would be to capture SIGABRT as you suggest. However I see a few requirements:

  1. A way to distinguish a call to assert() from the other possible causes of SIGABRT being received. That could be a call kill() from another thread or process, or even a call to abort() itself from the sanity checks of the heap management functions (free(), malloc() ...). This can be done by the ABRT signal handler, by checking the execution stack of the process or the context passed to sigaction() in some systems (that void* parameter nobody knows how to use).

  2. If you decide to capture SIGABRT you should bear in mind that signal handlers are not "legally" allowed to do much (not even a call printf), which make them bad candidates to do "something more useful" as you ask.

    So it would be better to have a dedicated thread permanently awating for the signal with sigwait() (based on how abort() is implemented this might not be an option) or notified by the signal handler whenever a signal is received ao that it can do the bulk of the work out of a signal handler context.

    Also, it is important to note that, if in its implementation, SIGABRT is sent by abort() specifically to its calling thread then its reception will be synchronous and you are free to call asynchronous-unsafe functions.

  3. By capturing the signal yourself and modifying the signal mask of the threads you might impact the signal behaviour of those third party libraries you mention (they could be capturing SIGABRT themselves).

  4. Even if you capture SIGABRT with your own signal handler you wont be able to return to normal execution the signal was sent from a call to abort() because (quoting from alarm(8)):

If the SIGABRT signal is ignored, or caught by a handler that returns, the abort() function will still terminate the process. It does this by restoring the default disposition for SIGABRT and then raising the signal for a second time.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top