Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why my linux signal handler run only once

Tags:

c++

linux

signals

#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 ?

like image 372
Henry Fané Avatar asked Oct 20 '25 01:10

Henry Fané


2 Answers

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.

like image 135
Tomer Vromen Avatar answered Oct 21 '25 15:10

Tomer Vromen


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.

like image 23
coryan Avatar answered Oct 21 '25 15:10

coryan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!