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:
-
In case of
SIG_DFL
the function pointer points to address0
(which is obviously no valid address). Thus, you have to reset the handler andraise()
the signal again.if (previous_handler == SIG_DFL) { signal(sig, SIG_DFL); raise(sig); signal(sig, myhandler); }
-
SIG_IGN
has value1
(also an invalid address). Here you can just return (do nothing).else if (previous_handler == SIG_IGN) { return; }
-
Otherwise (neither
SIG_IGN
norSIG_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()
).