#include <iostream>
#include <signal.h>
#include <fenv.h>
#include <string.h>
void signal_handler(int sig, siginfo_t *siginfo, void* context)
{
std::cout << " signal_handler " << fetestexcept(FE_ALL_EXCEPT) << std::endl;
throw "exception";
}
void divide() {
float a = 1000., b = 0., c, f = 1e-300;
c = a / b;
std::cout << c << " and f = " << f << std::endl;
}
void init_sig_hanlder() {
feenableexcept(FE_ALL_EXCEPT);
struct sigaction sa, initial_sa;
sa.sa_sigaction = &signal_handler ;
sigemptyset( &sa.sa_mask ) ;
sa.sa_flags = SA_SIGINFO; // man sigaction(3) // allows for void(*)(int,siginfo_t*,void*) handler
sigaction(SIGFPE, &sa, &initial_sa);
}
int main(int argc, char** argv) {
init_sig_hanlder();
while(true)
{
try {
sleep(1);
divide();
}
catch(const char * a) {
std::cout << "Exception in catch: " << a << std::endl;
}
catch(...) {
std::cout << "Exception in ..." << std::endl;
}
}
return 0;
}
Produce the following results on Linux/g++4.2:
signal_handler 0
Exception in catch: exception
inf and f = 0
inf and f = 0
inf and f = 0
inf and f = 0
So, signal handler is executed the first time but the next fp exception does not trigger the handler again. Where am I wrong ?
I don't think throwing an exception inside a signal handler is good practice. The operating system expects the signal handler to return
, because the signal is blocked while the handler for it is called. By throwing an exception you prevent the system from unblocking the signal.
As I recall signal handlers have to be declared 'extern "C"' because the library / kernel is going to use C calling conventions, not the C++ calling convention, for your function. But functions that are extern "C" cannot throw exceptions, so at least formally your code is not "right"
Under the hood, I would guess the signal delivery code in Linux does not have a chance to reset or clear the signal masks because you never returned control to the runtime and the kernel.
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