2010-09-29 21 views
17

Uso pthread_create per creare più thread figlio. Alla volta, il thread principale vuole uccidere tutti i thread figli o ci sarà il falut del segmento. Quale funzione dovrei usare per finire? Ho cercato la risposta da google e ho ottenuto funzioni come pthread_kill. Ma non sapevo quale segnale dovrei inviare al thread secondario per ucciderli. Il mio ambiente di esecuzione è RHEL 5.4 e il linguaggio di programmazione è C.Per pthread, Come uccidere thread secondario dal thread principale

+2

wow, uccide tutto il thread perché ci sarà un segfault? stai scherzando? Non avrei mai un po 'di codice gestito in quel modo. –

+1

Veramente parlando, ho gdb il core dump trovato quando gli oggetti globali di uscita del thread principale sono stati decostruiti. Quindi alcuni thread figlio possono attualmente utilizzare tale variabile e il difetto di segmento viene stampato sul mio schermo. Sebbene, la logica sia corretta e l'errore di segmento non avrà alcun effetto sul mio programma perché è finito. – terry

+2

Risolve la logica. Se gli altri thread stanno ancora facendo un lavoro utile, perché stai cercando di terminare il programma? Se gli altri thread hanno ancora bisogno di questi oggetti anche quando 'main' esce dall'ambito, perché sono allocati nello stack' main's? –

risposta

20

È possibile "annullare" una discussione utilizzando pthread_cancel. Tuttavia, questo non è in genere la migliore pratica anche se in circostanze estreme come un SEGFAULT può essere considerato un approccio ragionevole.

+1

C'è un esempio in questo url http://linux.die.net/man/3/pthread_cleanup_push – enthusiasticgeek

+4

Perché 'pthread_cancel' non è considerato una buona pratica? E se non è la migliore pratica, che cos'è? – darnir

6

è necessario inviare SIG_TERM a ciascuno dei vostri fili, utilizzando

int pthread_kill(pthread_t thread, int sig); 

Un modo rapido per sbarazzarsi di tutte le discussioni (oltre al principale) è quello di fork() e andare avanti con il bambino.
Non iper pulito ...

if (fork()) exit(0); // deals also with -1... 
24

In generale, non si vuole veramente uccidere violentemente un thread figlio, ma invece si vuole chiedere a terminare. In questo modo puoi essere certo che il bambino si fermi in un posto sicuro e che tutte le sue risorse vengano pulite.

Generalmente faccio questo con un piccolo frammento di stato condiviso tra genitore e figlio per consentire al genitore di comunicare una "richiesta di chiusura" a ogni bambino. Questo può essere solo un valore booleano per ogni bambino, protetto da un mutex. Il bambino controlla periodicamente questo valore (ogni iterazione del ciclo o qualsiasi altro punto di controllo appropriato nel thread secondario). Quando viene visualizzato il messaggio "quit_request", il thread secondario pulisce e chiama pthread_exit.

Sul lato genitore, la routine "kill_child" sembra qualcosa di simile:

acquire shared mutex 
set quit_request to true 
pthread_join the child 

La pthread_join potrebbe richiedere del tempo, a seconda di come spesso il bambino controlla il suo uscire richiesta. Assicurati che il tuo design sia in grado di gestire qualsiasi ritardo.

+0

Mentre è generalmente buona norma acquisire un mutex prima di modificare qualsiasi memoria condivisa tra i thread, il fatto che si tratti di un singolo flag che viene controllato per lo stato diverso da zero (o falso), significa che non hai davvero bisogno per prendere un mutex. In questo caso, non c'è davvero molto che possa andare storto dal punto di vista della coerenza dei dati. –

+2

@Brent: [Questa domanda] (http://stackoverflow.com/questions/21183261/is-a-race-condition-possible-when-only-one-thread-writes-to-a-bool-variable-in -c) mostra un esempio in cui anche una singola bandiera scritta una volta può portare a una condizione di competizione dopo ottimizzazioni del compilatore. – dshepherd

+0

Bello, questo funziona meravigliosamente. – djthoms

2

È possibile utilizzare una variabile globale per l'intero programma.

int _fCloseThreads;

Impostarlo su 1 quando si desidera che i thread terminino l'esecuzione. I thread controllano tale variabile nel loro "ciclo" e si chiudono piacevolmente quando sono impostati su 1. Non c'è bisogno di proteggerlo con un mutex.

È necessario attendere la chiusura dei thread. Puoi usare join. Un altro modo è quello di incrementare un contatore quando un thread entra nel suo thread proc e quindi decrive il contatore quando esce. Il contatore dovrebbe essere un tipo globale. Usa le operazioni atomiche di gcc sul contatore. Il thread principale, dopo aver impostato fCloseThreads, può attendere sul contatore per andare a zero eseguendo il loop, dormendo e controllando il conteggio.

Infine, è possibile eseguire il checkout di pthread_cleanup_push e pop. Sono un modello per consentire a un thread di cancellare ovunque nel suo codice (utilizza un longjump) e quindi chiamare una funzione di cleanup finale prima di uscire da threadproc. In pratica metti cleanup_push nella parte superiore del tuo threadproc e cleanup_pop nella parte inferiore, crea una funzione di svolgimento, e quindi in determinati punti di annullamento un thread annullato da una chiamata a pthread_cancel() tornerà indietro a threadproc e chiamerà la funzione unwind.

+1

http://linux.die.net/man/3/pthread_cleanup_push ha un esempio. – enthusiasticgeek

Problemi correlati