Bonjour,
J'ai un souci avec les sémaphore Posix anonyme utilisés dans la synchronisation de threads. Je tiens d'abords à poser le contexte.. attention, accrochez-vous!
Mes threads permettent d'activer certaines sous-routines qui sont chacune liées à un flag. Ceux-ci sont testés dans une boucle infinie exécutée dans le thread qui est bloqué à chaque boucle par un sémaphore (sem_wait()). Avec le code, ce sera peut-être plus clair :
Code :
- //fonction exécutée dans un thread détaché du fil d'exécution principal du programme
- void maFonctionThreadee()
- {
- while(true)
- {
- if(maSousRoutine1_activee)
- {
- maSousRoutine1_activee = false;
- maSousRoutine1_Privee();
- }
- else if(maSousRoutine2_activee)
- {
- maSousRoutine2_activee = false;
- maSousRoutine2_Privee();
- }
- //...
-
- //arrête le thread jusqu'à la prochaine activation
- sem_wait(&monSemaphore);
- }
- }
- //fonction public appelée depuis le fil d'exécution principal du programme
- void MaSousRoutine1_Public()
- {
- maSousRoutine1_activee = true;
- //activation de la boucle dans la fonction "threadée"
- sem_post(&monSemaphore);
- }
- //fonction privée, appelée depuis la boucle de la fonction "threadée"
- void maSousRoutine1_Privee()
- {
- //code traitement
- }
|
Je dois interrompre ce thread de manière asynchrone.
J'arrive à le faire car lors de l'initialisation du thread, je paramètre l'activation des interruptions avec :
Code :
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
Et je l'interromps avec l'appel à la fonction :
Code :
- pthread_cancel(referenceAuThread);
|
Le thread s'interrompt bien.
Lorsque je réinitialise le thread, je réinitialise en premier les flags d'activation relatifs aux sous-routines, ainsi que le sémaphore utilisé pour bloquer/activer la boucle de la manière suivante :
Code :
- //destruction de l'ancien sémaphore
- sem_destroy (&monSemaphore);
- //initialisation du nouveau sémaphore
- //(initialiser à 0, ainsi au premier sem_wait, il attendra jusqu'à qu'on active
- //une des sous-routine et qu'un sem_post soit effectué).
- sem_init(&monSemaphore, 0, 0);
|
Ensuite, l'initialisation du thread :
Code :
- // le thread est detaché
- pthread_attr_setdetachstate(&pthread_attr_t,PTHREAD_CREATE_DETACHED);
- //initialise le thread et le lance dans la méthode maFonctionThreadee
- pthread_create(&referenceAuThread, &pthread_attr_t, maFonctionThreadee)
|
Voilà, donc pour en arriver au fait.. J'arrive à interrompre mes threads, à les réinitialiser et à les relancer. Cependant, parfois de manière inattendue, après avoir relancer mes threads, lorsque j'effectue un sem_post sur le sémaphore monSemaphore pour activer la boucle, celui-ci s'incrémente bien (j'ai vérifié avec la fonction sem_getvalue()), mais le thread en attente sur le sem_wait dans la boucle infinie ne se débloque pas...
J'ai lu dans la doc MAN, que de faire un sem_destroy(&monSemaphore) alors que ce sémaphore a des threads en attente, peut amener un comportement indéfini :
Citation :
“Destroying a semaphore that other processes or threads are currently blocked on (in sem_wait(3)) produces undefined behaviour.”
|
Linux MAN page
8O
Est-ce que cela pourrait-il être la cause de mon problème? Pourtant, j'ai l'impression de tout réinitialiser proprement et deux fois sur trois, cela fonctionne très bien.. Vive les bugs de concurrence!
Merci d'avance pour votre aide, j'en ai un grand besoin! :?
Alex