Reputation: 3101
Under Win32 it's easy to convert a SEH-exception into a C++-exception with _set_se_translator. Is there a similar way to convert certain signals into C++-exceptions on Linux? I need a mapping of SIGFPE to a C++-exception.
Upvotes: 5
Views: 1719
Reputation: 1
You cannot do reliably that on POSIX systems such as Linux. See also this for more details. Notice that you can't use signalfd(2) in your case. I assume you are using Linux on x86-64 or some other commonly available architecture.
Read very carefully signal(7) (in particular what is said about async-signal-safe functions in signal handlers, and they are the only way to handle signals like SIGFLE
). Read also what the C++11 standard or the C99 standard say about signal
. Most C++ implementations might sometimes generate some implicit call to runtime support functions which are not async-signal-safe (in particular, those for throwing an exception. So you cannot reliably throw an exception from a signal handler).
In practice, the following would be a wrong signal handler:
/// WRONG CODE, against signal(7) since calling
/// non-async-signal-safe functions from the C++ runtime
void badSIGFPEhandler(int sig) {
if (sig == SIGFPE)
throw std::runtime_error("got SIGFPE");
}
You can check by compiling it with g++ -Wall -O -fverbose-asm -S
(then looking into the emitted .s
assembler file) that it is calling some non-async-signal-safe functions (from the C++ runtime) like __cxa_allocate_exception
, __cxa_throw
, _Unwind_Resume
which is forbidden by signal(7)....
In practice, the only safe thing to do from a signal handler which does not abort
or _exit
is to set some volatile sigatomic_t
flag, or use the few async-signal-safe functions, e.g. write(2) something on a pipe(7). Also, throwing an exception from a signal handler is not worse than calling printf
from it (lots of people are wrongly doing it); it is forbidden, but it could often work. I still don't recommend doing that, in particular in programs which are running for a long time, or for which crashing -even infrequently- is not acceptable.
Read more about undefined behavior, notably Lattner's blog about What every C programmer should know about undefined behavior.
In practice, the only reliable and portable way to handle signals is to have a signal handler which just sets some volatile sigatomic_t
flag. But if you do that for SIGFPE
your implementation is very likely to restart the same computation in the same state, hence looping indefinitely on SIGFPE
handling. See also this regarding -fnon-call-exceptions
(so I believe that n.m.'s answer might not always be right and reliable; it is in fact undefined behavior which would often seem to work).
PS. Actually, I strongly suspect that Windows way of doing that conversion is not C++11 or C++14 standard (or C99 or C11 standard) conforming, and you could have a standard conforming implementation of C++ (or C99 or C11) on Windows which disallows doing what you suggest; and probably Clang or GCC are such implementations.
Upvotes: 2
Reputation: 119847
With g++, you can use -fnon-call-exceptions
option and just throw an exception from the FPE signal handler. Note not every signal can be mapped like that, only signals that arise from trapping instructions. Fortunately SIGFPE is such a signal.
Upvotes: 4