2013-06-14 9 views

risposta

14

Come detto da altri, è possibile impostare un solo gestore di segnale, che è l'ultimo. Dovresti quindi gestire autonomamente due funzioni. La funzione sigaction può restituire il gestore di segnale installato in precedenza, che è possibile chiamare.

Qualcosa di simile (codice non testato):

/* 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); 
+0

Non ci manca un ritorno '; se (lib1_sighandler)' blocco ''? –

+0

@rajraj, no, perché? Dobbiamo chiamare ** entrambi i ** gestori. "If" si limita a far sì che i puntatori non siano NULL. Per ogni evenienza, dal momento che non vuoi entrare in crash all'interno di un gestore di segnali. – Shahbaz

1

siamo in grado di gestire più segnali con gestore di segnale singolo ma ma non è possibile avere più gestori di segnale per lo stesso segnale.

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; 
    } 

se si tenta di eseguire questo codice, si scoprirà che l'ultimo gestore di segnale assegnato è impostato per quel segnale. Penso che non sia possibile avere un gestore di segnali multipli per lo stesso segnale.

6

È possibile installare un solo gestore di segnale per segnale. Sarà attivo solo l'ultimo gestore installato.

1

Come si può vedere nella pagina man per sigaction, il nuovo gestore di segnale sostituisce il vecchio e viene restituito quello vecchio.

Se si dispone di due segnali inutilizzati (ad esempio SIGUSR1 e SIGUSR2), assegnare a tali segnali i due gestori di segnale per SIGINT. Quindi è possibile scrivere il proprio Signal Handler per SIGINT e da questo, è possibile aumentare il segnale inutilizzato necessario secondo le proprie esigenze.

1

Shabaz ha colpito il chiodo sulla testa. Tuttavia, se siete alla ricerca di qualcosa di tutte le librerie potrebbero usare (a patto di avere accesso al codice sorgente), si potrebbe fare qualcosa secondo le seguenti linee:

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); 
    ... 
} 

Oppure, si potrebbe utilizzare da soli, e dopo aver caricato ciascuna libreria, ottenere il gestore e in seguito chiamare add_handler. Qualcosa sulla falsariga di:

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); 

Solo alcuni pensieri, Anthony