Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

executing default signal handler

Tags:

I have written an application where i have registered number of signal handler for different signals in linux . After process receives the signal the control is transferred to the signal handler i had registered. In this signal handler i do some work which i need to do, and then i would like to call the default signal hander i.e SIF_DFL or SIG_IGN . However, SIG_DFL and SIG_ING are both macros which expand to numeric values 0 and 1 respectively, which are invalid function addresses.

IS there any way i can call default actions i.e SIG_DFL or SIG_IGN ?

In order to achieve the effect of SIG_DFL or SIG_ING i call exit(1) and do nothing , respectively . But for signals like SIGSEGV i also would like to have core dump . In general i would want to my default behavior to be same as SIG_DFL and ignore behavior same SIG_IGN , the way Operating system would do .

like image 546
app Avatar asked May 16 '11 09:05

app


People also ask

What is a default signal handler?

A Default signal handler is associated with every signal that the kernel runs when handling that signal. The action that a script or program performs when it receives a signal is called the default actions. A default signal handler handles these types of different default actions.

What is the default action for signals?

Signal dispositions Each signal has a current disposition, which determines how the process behaves when it is delivered the signal. Default action is to terminate the process. Default action is to ignore the signal.

How does a signal handler work?

A signal handler is a function which is called by the target environment when the corresponding signal occurs. The target environment suspends execution of the program until the signal handler returns or calls longjmp() . Signal handlers can be set with signal() or sigaction() .

Are signal handlers executed in user mode?

The handle_signal( ) function runs in Kernel Mode while signal handlers run in User Mode; this means that the current process must first execute the signal handler in User Mode before being allowed to resume its "normal" execution.


2 Answers

The GNU C Library Reference Manual has a whole chapter explaining everything about signal handling.

You always get the previously set signal handler (a function pointer) when you install your own handler (see manpages for signal() or sigaction()).

previous_handler = signal(SIGINT, myhandler); 

The general rule is, that you can always reset to the previous handler and raise() the signal again.

void myhandler(int sig) {   /* own stuff .. */   signal(sig, previous_handler);   raise(sig);   /* when it returns here .. set our signal handler again */   signal(sig, myhandler); } 

There is one disadvantage of the general rule: Hardware exceptions which are mapped to signals are usually assigned to a certain instruction which caused the exception. So, when you raise a signal again, the associated instruction is not the same as originally. This can but should not harm other signal handlers.

Another disadvantage is, that each raised signal causes a lot of processing time. To prevent excessive use of raise() you can use the following alternatives:

  1. In case of SIG_DFL the function pointer points to address 0 (which is obviously no valid address). Thus, you have to reset the handler and raise() the signal again.

    if (previous_handler == SIG_DFL) {   signal(sig, SIG_DFL);   raise(sig);   signal(sig, myhandler); } 
  2. SIG_IGN has value 1 (also an invalid address). Here you can just return (do nothing).

    else if (previous_handler == SIG_IGN) {   return; } 
  3. Otherwise (neither SIG_IGN nor SIG_DFL) you have received a valid function pointer and you can call the handler directly,

    else {   previous_handler(sig); }

Of course, you have to consider the different APIs as well (see manpages for signal() and sigaction()).

like image 198
homac Avatar answered Oct 10 '22 02:10

homac


You can save the previous handler and then call it when the time is right.

Install handler. Make sure you save old handler

static struct sigaction new_sa, old_sa;  new_sa.sa_handler = my_handler; sigemptyset(&new_handler.sa_mask);  if (sigaction(signo, &new_sa, &old_sa) == -1) {     /* handle sigaction error */ } 

In your new handler, call the old handler

(*old_sa.sa_handler)(signo) 

You don't need to raise it again or do any messy stuff; simply call the old handler (of course, since you saved the sigaction you have acces to the old disposition and so on).

like image 38
cnicutar Avatar answered Oct 10 '22 04:10

cnicutar