I am reading The Design and Evolution of C++, by Bjarne Stroustrup. Regarding exeception handling and asynchronous signals it is mentioned as below:
Can exceptions be used to handle things like signals? Almost certainly not in most C environments. The trouble is that C uses functions like malloc that are not re-entrant. If an interrupt occurs in the middle of malloc and causes an exception, there is no way to prevent the exception handler from executing malloc again.
A C++ implementation where calling sequences and the entire run-time library are designed around the requirement for re-entrancy would make it possible for signals to throw exceptoins
What does the author mean by the statement "there is no way to prevent the exception handler from executing malloc again"? How would making functions re-entrant make it possible to throw exceptions from signal handlers?
In my opinion that part doesn't really make much sense with current C++.
In C++ there is no way to use an exception as a signal because signals are meant to be executing an handler and then (possibly) continue execution.
C++ exceptions however don't work this way. Once you get to the exception handler the stack has been already rolled back and there is no way to "continue" after the handling: there is no way to get to the statement following a throw (or following a function call during which an exception gets thrown).
Signals are asynchronous but not disruptive and continuing after a signal is possible (even if of course care must be taken about what is done in the signal handler), exceptions instead are disruptive of the program flow and continuing is impossible.
I'd say the two ideas are incompatible at a logical level and doesn't really matter if the library is reentrant or not.
May be in early C++ design there was a resume option for exceptions...
If for example, a call to malloc induced a signal then if you threw an exception from that signal handler malloc could be called again by the exception throwing logic. Since malloc isn't reentrant you'd wind up with undefined behavior.
One way to deal with signals is to just push a signal event into your event queue and return from the signal handler immediately. Then when the event loop processes the signal event it can do whatever it wants since it isn't in the restricted context of a signal handler.
A function is "reentrant" if it can be interrupted in the middle of execution and called again before that interrupted call completes. Another way to look at it: A reentrant function can be called from within a signal handler. All bets are off on calling a non-reentrant function from within a signal handler. The only functions that should be called from inside a signal handler are those functions that are known to be reentrant.
malloc is not reentrant. If malloc goes kaboom there is no way of telling if it went kaboom in the middle of updating whatever global data malloc uses behind the scenes to keep track of allocated data.
Another problem with signal handlers versus exceptions: Code executing in a signal handler is essentially running in a different thread than the main code. If the signal can be addressed, a return from the signal handler returns to just after the point where the signal was raised. How are you going to throw an exception in a signal handler? Do that and the signal handler is no longer returning! That means the rest of the execution is effectively done from within the signal handler. Now what happens when another signal occurs? The two concepts just don't mix. Reentrancy is just the tip of the iceberg here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With