I have two shared libraries linked to my test application. Both of the libraries have signal handlers for SIGINT
.
Is it valid to have multiple signal handlers for same signal? Which order the handlers will execute when I generate a SIGINT
signal?
As said by others, only one signal handler can be set, which is the last one. You would then have to manage calling two functions yourself. The sigaction
function can return the previously installed signal handler which you can call yourself.
Something like this (untested code):
/* other signal handlers */
static void (*lib1_sighandler)(int) = NULL;
static void (*lib2_sighandler)(int) = NULL;
static void aggregate_handler(int signum)
{
/* your own cleanup */
if (lib1_sighandler)
lib1_sighandler(signum);
if (lib2_sighandler)
lib2_sighandler(signum);
}
... (later in main)
struct sigaction sa;
struct sigaction old;
lib1_init(...);
/* retrieve lib1's sig handler */
sigaction(SIGINT, NULL, &old);
lib1_sighandler = old.sa_handler;
lib2_init(...);
/* retrieve lib2's sig handler */
sigaction(SIGINT, NULL, &old);
lib2_sighandler = old.sa_handler;
/* set our own sig handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = aggregate_handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
Only one signal handler can be installed per signal. Only the latest installed handler will be active.
we can handle multiple signal with single signal handler but
but its is not possible to have multiple signal handler for same signal.
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT 1\n");
}
void sig(int signo)
{
if (signo == SIGINT)
printf("received SIGINT 2\n");
}
int main(void)
{
if(signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
if (signal(SIGINT, sig) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
// A long long wait so that we can easily issue a signal to this process
while(1)
sleep(1);
return 0;
}
if u try to run this code u will find that the last assigned signal handler is set for that signal.
i think it is not possible to have a multiple signal handler for same signal.
As you could see in the man page for sigaction, the new signal handler replaces the old one and the old one is returned.
If you have two unused signals (say SIGUSR1
and SIGUSR2
), assign those signals the two signal handlers for SIGINT
. Then you may write your own Signal Handler for SIGINT
and from that, you may raise the needed unused signal as per you want.
Shabaz hit the nail on the head. However, if you're looking for something all your libraries could use (provided you have access to the source code), you could do something along the following lines:
linked_list* sigint_handlers = NULL;
void sighand_init(sighand_config_t* config) {
struct sigaction action;
memset(&signalaction, 0, sizeof(signalaction));
action.sa_handler = &sighand_main;
// Order is important, in case we get a signal during start-up
sigint_handlers = linked_list_new();
sigaction(SIGINT, &action);
}
void sighand_main(int signum) {
if (signum == SIGINT) {
linked_list_node* node = linked_list_head(sigint_handlers);
while ((node = node->next) != NULL) {
node->object(signum);
}
if (sighand_config.exitonint) {
app_exit(0);
}
}
}
void sighand_add_int_handler(void (*handler)(int)) {
if (handler == NULL) return;
linked_list_add(sigint_handlers, handler);
}
void sighand_destroy() {
...
linked_list_destroy(signint_handlers);
...
}
Or, you could use this yourself, and after loading each library, get the handler and later call add_handler. Something along the lines of:
loadlibrary(lib1.so);
sigaction1 = signalget(SIGINT);
loadlibrary(lib2.so);
sigaction2 = signalget(SIGINT);
sighand_init(...);
sighand_add_int_handler(sigaction1.sa_handler);
sighand_add_int_handler(sigaction2.sa_handler);
Just some thoughts,
Anthony