Semplice pthread indipendente non cancella! (Blocchi cout e intercalari anche se mutexed)
Domanda
Ho un problema difficile qui, che non riesco a risolvere e non trovare la risposta giusta in rete:
Ho creato un filo staccato con un instradamento pulizia, il problema è che sul mio iMac e Ubuntu 9.1 (Dual Core). Io non sono in grado di annullare correttamente il filo staccato nel codice maggese:
#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <time.h>
pthread_mutex_t mutex_t;
using namespace std;
static void cleanup(void *arg){
pthread_mutex_lock(&mutex_t);
cout << " doing clean up"<<endl;
pthread_mutex_unlock(&mutex_t);
}
static void *thread(void *aArgument)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
pthread_cleanup_push(&cleanup,NULL);
int n=0;
while(1){
pthread_testcancel();
sched_yield();
n++;
pthread_mutex_lock(&mutex_t);
cout << " Thread 2: "<< n<<endl; // IF I remove this endl; --> IT WORKS!!??
pthread_mutex_unlock(&mutex_t);
}
pthread_cleanup_pop(0);
return NULL;
}
int main()
{
pthread_t thread_id;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
int error;
if (pthread_mutex_init(&mutex_t,NULL) != 0) return 1;
if (pthread_create(&thread_id, &attr, &(thread) , NULL) != 0) return 1;
pthread_mutex_lock(&mutex_t);
cout << "waiting 1s for thread...\n" <<endl;
pthread_mutex_unlock(&mutex_t);
int n =0;
while(n<1E3){
pthread_testcancel();
sched_yield();
n++;
pthread_mutex_lock(&mutex_t);
cout << " Thread 1: "<< n<<endl;
pthread_mutex_unlock(&mutex_t);
}
pthread_mutex_lock(&mutex_t);
cout << "canceling thread...\n" <<endl;
pthread_mutex_unlock(&mutex_t);
if (pthread_cancel(thread_id) == 0)
{
//This doesn't wait for the thread to exit
pthread_mutex_lock(&mutex_t);
cout << "detaching thread...\n"<<endl;
pthread_mutex_unlock(&mutex_t);
pthread_detach(thread_id);
while (pthread_kill(thread_id,0)==0)
{
sched_yield();
}
pthread_mutex_lock(&mutex_t);
cout << "thread is canceled";
pthread_mutex_unlock(&mutex_t);
}
pthread_mutex_lock(&mutex_t);
cout << "exit"<<endl;
pthread_mutex_unlock(&mutex_t);
return 0;
}
Quando si sostituisce la Cout con printf () i Workes fino alla fine "uscita", ma con il cout (anche bloccato) si blocca l'eseguibile dopo output "filo distacco ...
Sarebbe molto bello sapere da un Pro, qual è il problema qui è ?. Perché questo non funziona anche quando cout è bloccato da un mutex!?
Soluzione
IL problema soltanto risiede in quel COUT ha un punto di cancellazione implicita!
Abbiamo bisogno di codice come questo:
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
e fare il filo all'inizio:
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
che garantisce che solo pthread_cancel () ha un punto di cancellazione ...
Altri suggerimenti
Provare a commentare la linea di pthread_detach(thread_id);
ed eseguirlo. Si sta creando il filo come indipendente con il vostro pthread_attr_t.
O che, o cercare passando NULL anziché & attr nel pthread_create (in modo che il filo è non creato distaccato) ed eseguirlo.
Direi che se il momento è giusto, il (già monofamiliare) filo è andato per il momento il thread principale tenta il pthread_detach, e si sta andando fuori in Never Never Land in pthread_detach.
Modifica:
Se cout ha un punto di cancellazione implicita come sottolinea Gabriel fuori, quindi molto probabilmente ciò che accade è che il filo annulla mentre si tiene il mutex (non è mai lo rende al pthreads_unlock_mutex dopo il cout), e così chiunque altro in attesa sul mutex sarà essere bloccato per sempre.
Se l'unica risorsa che dovete preoccupare è il mutex, si potrebbe tenere traccia di se o non è il tuo thread è esso bloccato e poi sbloccarlo nella pulizia, partendo dal presupposto che la pulizia viene eseguito nello stesso thread.
Date un'occhiata qui, pagina 157 sopra: pthread Primer .