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:
A way to distinguish a call to
assert()
from the other possible causes of SIGABRT being received. That could be a callkill()
from another thread or process, or even a call toabort()
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 tosigaction()
in some systems (that void* parameter nobody knows how to use).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 howabort()
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.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).
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.