2012-01-29 7 views
5

Nella mia applicazione il thread principale crea due thread uniti; uno che attende l'input dell'utente chiamando scanf() in un ciclo e un altro che ascolta le connessioni socket in entrata chiamando accept() in un ciclo. Le nuove connessioni vengono gestite in thread separati che vengono separati.Interruzione di due pthread di blocco tramite segnali

Desidero che il programma si chiuda correttamente quando viene ricevuto un segnale SIGINT. Ciò significa che il thread di ascolto dovrebbe smettere di accettare nuove connessioni, attendere che i thread che attualmente servono le connessioni si chiudano e poi. Anche il thread in attesa di input dell'utente dovrebbe terminare e quindi consentire la fine del thread principale.

Scanf() e accept() entrambi i blocchi ma possono essere interrotti da un segnale, tuttavia i segnali inviati al processo possono essere gestiti solo da un thread (AFAIK). La mia idea è di bloccare i segnali SIGINT in tutti i thread tranne il thread principale che lo aspetterà. Quando riceve un SIGINT, invierà SIGUSR1 ai due thread (uno che blocca su scanf() e uno che blocca su accept()) e quindi si unirà a questi thread.

Questa è una buona soluzione? C'è un modo migliore o forse standard per raggiungere questo obiettivo?

risposta

5

La soluzione canonica per problemi di questo tipo è Thread Cancellation. Una richiesta di cancellazione che arriva mentre una discussione è bloccata in una funzione che è un punto di annullamento verrà immediatamente applicata; in caso contrario, viene applicata la volta successiva che il thread chiama una funzione che è un punto di annullamento.

L'unica cosa che può essere dolorosa nell'usare la cancellazione è che si basa su un modello di gestione delle eccezioni piuttosto che su ritorni di errore. È necessario mantenere la cancellazione bloccata la maggior parte del tempo (e abilitarla solo durante le operazioni durante le quali si desidera gestire l'annullamento) oppure installare gestori di cancellazione cancellazione (fondamentalmente, gestori di eccezioni semi-brutti in C) a ogni livello di frame di chiamata in cui si potrebbe avere stato intermedio/allocazioni/ecc. per cancellare quando il tuo thread è cancellato. Personalmente preferisco il primo approccio, che generalmente richiede l'installazione di un solo gestore di cancellazione.

Qualsiasi approccio basato su interrupt di segnali ha intrinsecamente condizioni di gara. Se il segnale viene inviato appena prima che venga richiamata la funzione di blocco, quando il gestore di segnale ritorna, la funzione di blocco verrà richiamata e verrà bloccata indefinitamente (poiché il controllo per "è ora di uscire?" È già stato superato con successo).

+0

Grazie - Speravo segretamente che avresti risposto a questa domanda! Il problema è che, una volta che un thread è stato cancellato, ad esempio quando si blocca su accept(), non viene eseguita alcuna logica successiva. Ho bisogno che il thread attenda i thread distaccati che gestiscono le connessioni e quindi liberano risorse prima che escano. Come potrei ottenere questo? – SlappyTheFish

+0

ah, è pthread_cleanup_push() cosa intendevi per cleanup handler? Sembra che farà il trucco. – SlappyTheFish

+0

Sì, è così che usi la cancellazione. –

Problemi correlati