2011-11-11 17 views
9

Ho un'applicazione principale che genera un thread separato per elaborare i messaggi da una coda. Ho un problema su AIX quando premo CTRL-C poiché sembra che alcuni "handle di connessione" nel thread non siano più validi. Ho un hook di shutdown nel programma principale che cattura SIGINT ma su AIX sembra in qualche modo inviare un segnale anche al thread ... anche se questo non è realmente possibile da quello che sento ...Come bloccare tutti i SEGNALI nel thread SENZA usare SIGWAIT?

Essenzialmente I vorrei sapere se voglio che l'applicazione MAIN gestisca TUTTI i segnali a cui sono interessato e che il thread/i non gestisca MAI alcun segnale ... è questa "buona pratica"?

Se è così, come NON posso usare "sigwait" nel thread ... infatti non voglio alcun "codice segnale" nel thread/s ... essi semplicemente non devono ricevere alcun segnale.

ho svuotato tutti i segnali:

sigemptyset(&set); 

E ho posto il SIG_BLOCK

s = pthread_sigmask(SIG_BLOCK, &set, NULL); 

ecco un manichino di programmi di prova:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <errno.h> 

#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 

static void * threadMainLoop(){ 
    //Here I do not want the thread to use "sigwait".... 
    while(running == TRUE){ 
     //do some thread work and never have any signals come in 
    } 
} 

void shutdownHook(int sig){ 
    printf("\nCtrl-C pressed....shutdown hook in main...\n"); 
} 

void signalErrorHandler(int signum){ 
    printf("\nSignal error handler in main...\n"); 
} 

int main(int argc, char *argv[]){ 
    pthread_t thread; 
    sigset_t set; 
    int s; 

    //Catch the following signals in the MAIN thread 
    (void) signal(SIGINT, shutdownHook); 
    (void) signal(SIGSEGV, signalErrorHandler); 
    (void) signal(SIGBUS, signalErrorHandler); 
    (void) signal(SIGILL, signalErrorHandler); 
    (void) signal(SIGTERM, signalErrorHandler); 
    (void) signal(SIGABRT, signalErrorHandler); 

    sigemptyset(&set); //BLOCK all signals 

    s = pthread_sigmask(SIG_BLOCK, &set, NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_sigmask"); 

    s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_create"); 

    pause(); 
} 

Se ho appena creo un thread e avere, ad esempio, il gestore del segnale SIGINT nel thread MAIN ma NON ha il set SIG_BLOCK per il thre annuncio e l'utente colpisce CTRL-C .... il thread viene influenzato del tutto anche se il gestore di segnale nel thread principale viene eseguito? Che sembra essere quello che sto vedendo in AIX ;-(

Grazie per l'aiuto, molto apprezzati

Lynton

risposta

13

Con s = pthread_sigmask(SIG_BLOCK, &set, NULL);, non sei il blocco nulla

Usa:.

sigfillset(&set); 
sets = pthread_sigmask(SIG_SETMASK, &set, NULL); 

Se si desidera bloccare tutti i segnali, o esplicitamente aggiungere i segnali che si desidera bloccare la set se si sta utilizzando SIG_BLOC K.

Dopo aver creato i thread, è necessario ripristinare la maschera di segnale, altrimenti nessun thread catturerà alcun segnale.

Tuttavia, osservando la domanda precedente, è possibile che il filo che cattura il segnale non gestisca l'interruzione. Cioè, se sei bloccato a fare un syscall e arriva un segnale, quel syscall viene interrotto. Per alcuni sistemi operativi, la chiamata di sistema viene automaticamente chiamata di nuovo, alcuni restituiscono un errore e impostano errno su EINTR, che l'applicazione deve gestire, e potrebbero verificarsi problemi se ciò non viene gestito.

Invece, installare i gestori di segnale con sigaction() al posto di segnali(), e impostare il flag SA_RESTART, che farà sì che le chiamate di sistema per riavviare automaticamente nel caso in cui ha ottenuto interrotta da un segnale.

+0

Ciao, ma ho impostato "s = pthread_sigmask (SIG_BLOCK, & set, NULL);" e prova con CTRL-C che il thread non riceve il segnale? Ciò significa che lo sta bloccando? Se aggiungo "sigaddset (& set, SIGINT);" allora il filo riceve il segnale. Perdonami se sbaglio qui ... Sto ancora imparando .. ;-) Grazie per l'aiuto ;-) –

+0

Aggiornamento della risposta un po '.. La maschera del segnale è i segnali che non possono essere sollevati. Quindi se si firma sigaddset (e set, SIGINT); pthread_sigmask (SIG_BLOCK, & set, NULL); , SIGINT verrà impostato nella maschera singnal e ciò significa che il thread non lo riceverà. Se si crea un nuovo thread, quel thread eredita la maschera del segnale dal thread che lo ha creato. – nos

+0

Si noti che se si desidera un nuovo thread per iniziare con i segnali mascherato (di solito necessario per evitare condizioni di gara brutte) è necessario bloccare i segnali prima di chiamare 'pthread_create' e quindi ripristinare il vecchio maschera del segnale nel thread originale dopo' restituisce pthread_create' . –

-11

Progettazione ancora errata. Non utilizzare CTRL + C per interrompere un'applicazione in modo controllato. Utilizzare un'app controller progettata correttamente che sarà accessibile tramite CORBA, RMI o qualche altro metodo per interagire con l'utente e controllare l'app in background.

Divertiti ragazzi ...

Problemi correlati