2012-05-04 10 views
6

Sto lavorando su un programma con un numero fisso di thread in C usando i thread posix.Come essere avvisati quando un thread è stato terminato per qualche errore

Come posso essere avvisato quando un thread è stato terminato a causa di un errore?

C'è un segnale per rilevarlo?

In tal caso, il gestore di segnale può creare una nuova discussione per mantenere uguale il numero di thread?

+0

Sono curioso di sapere se questo può essere rilevato senza un thread di watchdog, ma sono abbastanza sicuro che devi lasciare la "ricreazione del thread morto" a un gestore thread al di fuori del gestore di segnale. (Ma non ho mai provato veramente a fare una cosa del genere, quindi potrei sbagliarmi) – Shahbaz

+1

Sono curioso di sapere cosa intendi con "terminato a causa di un errore". Se un thread seghaults l'intero processo insieme a tutti gli altri thread segfaults. – alk

+0

sto lavorando su un webserver multi-thread, quando il numero di thread è inferiore a un numero fisso, il server termina. Non so perché i thread vengono terminati nel programma, il server serve circa 1000 connessioni, quindi termina. – CodeRed

risposta

1
  1. Fai i fili staccati
  2. farli per gestire gli errori con grazia. vale a dire mutex, file ecc ...

Quindi non avrete problemi.

Forse sparano un segnale USR1 al thread principale per dirgli che le cose sono andate a forma di pera (stavo per dire tette in su!)

1

Crea le discussioni facendo passare i puntatori a funzione a una funzione intermedia. Avvia quella funzione intermedia in modo asincrono e chiama in modo sincrono la funzione passata. Quando la funzione restituisce o genera un'eccezione, puoi gestire i risultati nel modo che preferisci.

+0

Cosa succede se il thread riceve un segnale 'KILL'? (O qualsiasi segnale che toglie il controllo dal 'threadFn' in modo asincrono). La funzione intermedia non può gestire casi come il controllo verrà tolto dal 'threadFn' in modo asincrono e potrebbe non tornare alla funzione intermedia –

+0

Blocca tutti i segnali per tutti i thread del processo, ma un thread che non sta facendo altro che un do {sigwaitinfo(); } mentre (1) ;. In questo modo sei in grado di gestire segnali asincroni in modo [email protected] – alk

1

Con gli ultimi ingressi hai fornito, ti suggerisco di fare qualcosa di simile per ottenere il numero di thread di un processo particolare, ha Started-

#include<stdio.h> 
#define THRESHOLD 50 

int main() 
{ 
    unsigned count = 0; 
    FILE *a; 

    a = popen ("ps H `ps -A | grep a.out | awk '{print $1}'` | wc -l", "r"); 
    if (a == NULL) 
     printf ("Error in executing command\n"); 

    fscanf(a, "%d", &count); 

    if (count < THRESHOLD) 
    { 
     printf("Number of threads = %d\n", count-1); 
      // count - 1 in order to eliminate header. 
      // count - 2 if you don't want to include the main thread 

     /* Take action. May be start a new thread etc */ 
    } 

    return 0; 
} 

Note:

  • ps H visualizza tutti i thread.

  • $1 stampa la prima colonna in cui PID è visualizzato sul mio sistema Ubuntu. Il numero di colonna potrebbe cambiare a seconda del sistema

  • Sostituire a.out con il tuo nome processo

  • Gli apici inversi valuteranno l'espressione al loro interno e vi darà il PID del processo. Stiamo sfruttando il fatto che tutti i thread POSIX avranno lo stesso PID.

+0

Forse potresti almeno usare libprocps piuttosto che un 'system()' + 'fscanf()' che sono funzioni piuttosto pericolose da usare. Puoi anche guardare in 'gettid()' che ti dà l'identificatore del thread (id di compito di Linux) –

1

Dubito che Linux ti segnali quando un filo muore o esce per qualsiasi motivo. Puoi farlo manualmente però.

In primo luogo, prendiamo in considerazione 2 modi per il filo alla fine:

  • Si termina
  • Muore

Nel primo metodo, il filo stesso può dire a qualcuno (dir gestore thread) che è stato terminato. Il gestore thread genererà quindi un altro thread.

Nel secondo metodo, un thread di watchdog può tenere traccia di se i thread sono vivi o meno.Questo viene fatto più o meno così:

Thread: 
    while (do stuff) 
     this_thread->is_alive = true 
     work 

Watchdog: 
    for all threads t 
     t->timeout = 0 
    while (true) 
     for all threads t 
      if t->is_alive 
       t->timeout = 0 
       t->is_alive = false 
      else 
       ++t->timeout 
       if t->timeout > THRESHOLD 
        Thread has died! Tell the thread manager to respawn it 
+0

Concordo sulla prima possibilità di menzionare, ma per il secondo potresti essere così gentile da spiegare, cosa intendi esattamente con " muore ", se il thread non avesse commesso un" suicidio ", che sarebbe coperto dalla prima possibilità, in quale altro modo sarebbe finito, se non" pthread_cancel() "editato dall'esterno? – alk

+0

@alk, ho capito cosa stai dicendo. In un'applicazione di spazio utente Linux se un thread segfaults (ad esempio) muore l'intero processo. Non so se ci sono sistemi operativi là fuori dove questo non è vero, ma per lo meno, nello spazio del kernel di Linux un thread può oops senza un crash del kernel e questo è come si saprebbe se è vivo o morto . La domanda dell'OP è "come sapere se il thread è terminato a causa di un errore?". Presumo che l'OP abbia una situazione più complicata a portata di mano di un thread in uscita. Non so quale sia esattamente la situazione, quindi ho dato una soluzione generale. – Shahbaz

1

Se per qualsiasi motivo non si poteva andare per Ed Heal di "solo funzionare correttamente" -approach (che è la mia risposta preferita alla domanda del PO, btw), i pigri volpe potrebbe dare un'occhiata alle macro pthread_cleanup_push() e pthread_cleanup_pop() e pensare di includere il corpo dell'intera funzione del filo tra due macro.

1

Il modo pulito per sapere se un thread è fatto è chiamare pthread_join() contro quel thread.

// int pthread_join(pthread_t thread, void **retval); 
int retval = 0; 
int r = pthread_join(that_thread_id, &retval); 
... here you know that_thread_id returned ... 

Il problema con pthread_join(), se il filo non ritorna mai (continua a funzionare come previsto), allora si sono bloccate. Non è quindi molto utile nel tuo caso.

Tuttavia, si può effettivamente verificare se è possibile partecipare (tryjoin) come segue:

//int pthread_tryjoin_np(pthread_t thread, void **retval); 
int retval = 0; 
int r = pthread_tryjoin_np(that_thread_id, &relval); 

// here 'r' tells you whether the thread returned (joined) or not. 
if(r == 0) 
{ 
    // that_thread_id is done, create new thread here 
    ... 
} 
else if(errno != EBUSY) 
{ 
    // react to "weird" errors... (maybe a perror() at least?) 
} 
// else -- thread is still running 

C'è anche un temporizzata join che attendere il periodo di tempo specificato, come un paio di secondi. A seconda del numero di thread da controllare e se il tuo processo principale si trova in un'altra posizione, potrebbe essere una soluzione. Blocca sul thread 1 per 5 secondi, quindi sul thread 2 per 5 secondi, ecc. Che sarebbe 5.000 secondi per loop per 1.000 thread (circa 85 minuti per aggirare tutti i thread con il tempo necessario per gestire le cose ...)

C'è un codice di esempio nella pagina man che mostra come usare la funzione pthread_timedjoin_np(). Tutto quello che dovresti fare è mettere un ciclo per controllare ciascuno dei tuoi thread.

struct timespec ts; 
int s; 

... 

if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { 
/* Handle error */ 
} 

ts.tv_sec += 5; 

s = pthread_timedjoin_np(thread, NULL, &ts); 
if (s != 0) { 
    /* Handle error */ 
} 

Se il processo principale ha altre cose da fare, vorrei suggerire di non utilizzare la versione a tempo e basta andare attraverso tutti i fili il più velocemente possibile.

Problemi correlati