2010-03-13 5 views
2

J'ai un problème difficile ici, que je ne peux pas résoudre et ne trouve pas la bonne réponse sur le net:Simple pached détaché ne annule pas! (Blocs de cout et entrelace même si mutexed)

J'ai créé un thread détaché avec un routage de nettoyage, le problème est que sur mon Imac et Ubuntu 9.1 (Dual Core). Je ne suis pas en mesure d'annuler correctement le fil détaché dans le code de mise en jachère:

#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; 
} 

Quand je remplace le Cout avec printf() i workes à la fin « sortie », mais avec le Cout (même verrouillé) l'exécutable se bloque après la sortie « fil détachant ...

Il serait très cool de savoir d'un Pro, quel est le problème ici est ?. Pourquoi ça marche pas, même si cout est verrouillé par un mutex !?

Répondre

2

LE PROBELM réside dans le fait que COUT a un point d'annulation implicite!

Nous devons code comme ceci:

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); 
    pthread_testcancel(); 
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); 

et faire le fil au début:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); 

qui assure que seul pthread_cancel() a un point de ... cancelation

+0

N'est-il pas vrai que le thread ignorera les demandes d'annulation pendant que l'annulation est désactivée? –

+0

Oui, c'est le cas, mais parce que j'ai eu aussi des problèmes sans mutexes cout qui bloquait quelque chose parce que son thread n'est pas sécurisé et mon thread principal bloqué, j'ai décidé de ne permettre que l'annulation entre et désactiver :-) et ça marche très bien .... – Gabriel

+0

En fait, toute utilisation de 'cout' avec annulation est un comportement indéfini. POSIX ne spécifie aucune interaction pour l'annulation avec C++, et si vous utilisez l'annulation, vous devez vous assurer qu'il est désactivé pendant la durée de tout code C++ où l'exécution de destructeurs serait requise dans le cadre d'une terminaison de thread propre/sécurisé. –

1

Essayez de commenter la ligne pthread_detach(thread_id); et exécutez-le.Vous créez le fil détaché avec votre pthread_attr_t.Ou bien, ou essayez de passer NULL au lieu de & attr dans pthread_create (de sorte que le thread est pas créé) et exécutez-le.

Je suppose que si le timing est correct, le thread (déjà détaché) est parti au moment où le thread principal tente le pthread_detach, et vous allez dans Never Never Land dans pthread_detach.

Edit:

Si Cout a un point d'annulation implicite Gabriel souligne, alors très probablement ce qui se passe est que le fil annule tout en maintenant le mutex (il n'a jamais fait de pthreads_unlock_mutex après la Cout), etc. quelqu'un d'autre qui attend sur le mutex sera bloqué pour toujours. Si la seule ressource dont vous avez besoin est le mutex, vous pouvez savoir si votre thread l'a verrouillé et le déverrouiller dans le nettoyage, en supposant que le nettoyage s'exécute dans le même thread.

Jetez un oeil ici, page 157 sur: PThreads Primer.

+0

J'ai commenté le pthread_detach() (ne devrait pas être un problème car il devrait renvoyer un message d'erreur si le thread est déjà annulé) MAIS le thi C'est quand je lance ce programme ici sur Ubunutu 9.1. il se bloque dans -> while (pthread_kill (thread_id, 0) == 0) { sched_yield(); } MAIS quand je commente le << endl; dans cout << "Thread 2:" << n << endl; alors tout fonctionne bien, et il ne reste pas bloqué? mais pourquoi?, Je suis tellement confus ?? A cause de ce cout? tampon? mais c'est verrouillé? – Gabriel