Come @sarnold ha sottolineato, per impostazione predefinita il thread non può essere cancellato con pthread_cancel()
senza chiamare le funzioni che sono i punti di cancellazione ... ma questo può essere modificato utilizzando pthread_setcanceltype()
per impostare il tipo di annullamento del thread su asincrono anziché differito. Per fare ciò, aggiungere qualcosa come pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
all'inizio della funzione thread, prima di iniziare il ciclo. Potresti quindi interrompere la discussione chiamando pthread_cancel(th)
da main()
.
Nota, tuttavia, che la cancellazione dei thread in questo modo (sia asincrona o meno) non elimina le risorse allocate nella funzione thread (come notato da Kevin in un commento). Per fare questo in modo pulito, è possibile:
- Assicurarsi che il filo non fa nulla di cui ha bisogno per ripulire prima di uscire (ad esempio utilizzando
malloc()
di allocare un buffer)
- Assicurarsi di avere qualche modo di pulizia dopo il thread altrove, dopo che il thread è terminato
- Utilizzare
pthread_cleanup_push()
e pthread_cleanup_pop()
per aggiungere i gestori di pulitura per eliminare le risorse quando il thread viene annullato. Si noti che questo è ancora rischioso se il tipo di cancellazione è asincrono, poiché il thread potrebbe essere annullato tra l'allocazione di una risorsa e l'aggiunta del gestore di cleanup.
- Evitare l'uso di
pthread_cancel()
e fare in modo che il thread controlli alcune condizioni per determinare quando terminare (che verrebbe controllato in cicli di esecuzione prolungata). Poiché il thread verifica la terminazione stessa, può eseguire qualsiasi operazione di pulizia necessaria dopo il controllo.
Un modo di attuare l'ultima opzione è quella di utilizzare un mutex come flag, e prova con pthread_mutex_trylock()
avvolto in una funzione da utilizzare nelle prove ciclo:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while(!needQuit(mx)) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
Se il filo non è distaccato (generalmente non predefinito), è necessario chiamare pthread_join()
dopo aver arrestato il thread.Se il thread è staccato, non è necessario unirsi a esso, ma non si sa esattamente quando termina (o anche approssimativamente, a meno che non si aggiunga un altro modo per indicare la sua uscita).
L'annullamento di pthreads indica che il thread non ha la possibilità di pulire la memoria allocata. –
Ok, ho risolto questo problema avendo solo un 'keepalive = 1' globale. Quindi ho cambiato 'while (1)' in 'while (keepalive)'. Per uccidere il thread ora devo solo cambiare il valore della variabile keepalive a 0 e voilà! – Pithikos