2016-08-03 71 views
1

Ich habe einen Code geschrieben, wo ich zwei untergeordnete Threads aus dem übergeordneten Thread erstellt habe.Warum Child Threads lebendig nach dem Haupt Threads getötet werden?

Dann, mit dem Empfang eines Signals von einem anderen Terminal innerhalb dieser Kind-Threads, druckte ich die threadID und verließen den Thread.

Ich habe 2 Fragen.

  1. Ich erhalte das Signal vom untergeordneten Thread. Warum druckt es die threadID des übergeordneten Threads?

  2. Nachdem der Elternfaden getötet wurde, wie können die Kindfäden lebendig sein ??

Der Code:

void sig_handler(int signo) 
{ 
    if (signo == 1){ 
     printf("%d\n", pthread_self()); 
     pthread_exit(NULL); 
    } 
} 

void* doSomeThing(void* arg) 
{ 
    printf("In function -> %d\n", pthread_self()); 
    if (signal(1, sig_handler) == SIG_ERR) 
     printf("\ncan't catch SIGHUP\n"); 
    while(1) 
     sleep(1); 
    return NULL; 
} 

int main(int argc, char *argv[]) 
{ 
    printf("In function -> %d\n", pthread_self()); 
    char *ch1; 
    pthread_t tid1, tid2; 
    ch1 = "random"; 
    int ret1, ret2; 

    ret1 = pthread_create(&tid1, NULL, &doSomeThing, (void *) ch1); 
    ret2 = pthread_create(&tid2, NULL, &doSomeThing, (void *) ch1); 

    while(1) 
     sleep(1); 
    return 0; 
} 

Hier ist das Bild des Ausgangsklemme gegeben:

Die ersten 3 Zeilen sind die 3 threadID s. 1. ist der Main threadID s, dann die zwei sekundären Threads.

Dann die threadID s aus dem folgenden Codeblock gedruckt.

if (signo == 1){ 
    printf("%d\n", pthread_self()); 
    pthread_exit(NULL); 
} 

Warum passiert das ???

+1

'Signal' funktioniert nicht wirklich mit Threads. –

+0

Bedeutet das, dass die 'pthread_self()' Funktion nicht die richtige 'threadID' gibt ?? Wie heißt es nach dem Empfang des 'Signals'? – jbsu32

+1

@JishnuBanerjee 'pthread_self()' gibt die Thread-ID des aufrufenden Threads an. Aber das wirkliche Problem ist, dass es nicht möglich ist, pro-Thread Signalhandler zu haben; Signalverarbeitung ist prozessweit. Ein Beispiel in der verlinkten Manpage zum Blockieren von Signalen. –

Antwort

3

Signale werden an den Prozess geliefert, nicht an einzelne Threads. Sie können also keinen Signal-Handler für einen Thread haben, wie Sie es hier tun. Was Sie tun können, ist Blockieren von Signalen, die Sie interessiert sind mit pthread_sigmask() und lassen Sie einen dedizierten Thread Signale unter Verwendung sigwait() behandeln, die am häufigsten ist.

+1

Wie wird sig_handler() hier genau aufgerufen? Ich meine, dass OP jedes Mal, wenn sig_handler() aufgerufen wird, eine andere threadID erhält, d. H. OP sendet ein Signal. Wie verwaltet dieses spezielle Programm diese Signale? –

+1

Die von OP gesendeten Signale sind nicht spezifisch für einen Thread. Es ist prozessweit. Sie können also nicht sicher sein, an welchen Thread das Signal gesendet wird. 'Pthreads (7)' sagt: "POSIX.1 unterscheidet die Begriffe von Signalen, die auf den Prozess als Ganzes gerichtet sind und Signale, die auf einzelne Threads gerichtet sind. Nach POSIX.1, ein prozessgesteuertes Signal (send using kill (2) zum Beispiel) sollte von einem einzigen, beliebig ausgewählten Thread innerhalb des Prozesses behandelt werden. " Diese "willkürliche Signallieferung" bedeutet, dass jeder Thread das Signal empfangen und den Signalhandler aufrufen kann und seine threadID wird gedruckt. –

0

Außerdem können Sie async-signalsichere Funktionen nur innerhalb eines Signal-Handlers sicher aufrufen. Von the Linux signal man page:

Async-Signal sichere Funktionen

muss eine Signal-Handler-Funktion sehr vorsichtig sein, da die Verarbeitungs an anderer Stelle kann an einer beliebigen Stelle in der Ausführung des Programms unterbrochen werden. POSIX hat das Konzept der "sicheren Funktion". Wenn ein Signal die Ausführung einer unsicheren Funktion unterbricht, und Handler entweder ruft eine unsichere Funktion oder handler endet über einen Aufruf zu longjmp() oder siglongjmp() und das Programm anschließend ruft eine unsichere Funktion, dann das Verhalten der Programm ist nicht definiert.

Die verknüpfte Manpage enthält eine Liste von Funktionen, die innerhalb eines Signalhandlers sicher aufgerufen werden können. Wenn die Funktion nicht in dieser Liste ist, ist es unsicher, sie zu nennen. Keine Ausnahmen.

Beachten Sie, dass weder printf() noch pthread_exit() auf der Liste der async-signalsicheren Funktionen stehen.

Und pthread_exit() aus einem Signal-Handler schafft Probleme mehrere andere Aufruf:

  • Der Faden, der nicht unter Kontrolle der Regel beendet ist. In vielen Fällen kann das Signal an beliebige Thread geliefert werden.

  • Der ausgehende Thread kann Objekte in einem unbekannten Zustand belassen - ein Mutex kann beispielsweise durch einen Thread, der nicht mehr existiert, gesperrt werden.

  • Alle Thread-Bereinigungshandler registered with pthread_cleanup_push() werden auch aus einem Signal-Handler-Kontext heraus aufgerufen.