1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    août 2011
    Messages
    674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : août 2011
    Messages : 674
    Points : 344
    Points
    344

    Par défaut Thread bloqué sans raison apparente

    Bonjour, voici une trace d'exe du code figurant ci dessous:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Thread 139667325822720, je commence mon traitement 
    Thread 139667325822720, j'attends' 
    Thread 139667334215424, je commence mon traitement 
    Thread 139667334215424, j'attends' 
    Thread 139667275466496, je commence mon traitement 
    Thread 139667275466496, je débloques ceux en attente 
    Thread 139667275466496, je finis mon traitement
    Thread 139667325822720, je finis mon traitement
    Thread 139667334215424, je finis mon traitement
    ^C
    Le but est que NB_THREAD sont lancés, ils ne peuvent pas terminer leur traitement si au moins un certain nombre d'entre eux n'ont pas atteint la même portion de code.

    En gros pour finir leur exécution, on fait un rendez vous de thread. Dans le code ci dessous, on a 9 thread et le rendez vous est fixé à 3 threads.

    La trace est donc correcte

    T1 commence et attends
    T2 commence et attends
    T3 commence et réveille T1 et T2
    T1 termine
    T2 termine (l'ordre T1,T2 n'a pas d'importance).

    Sauf qu'il semblerait que par la suite je sois bloqué car je n'ai pas de nouveau thread qui commencent....et je ne comprends pas pourquoi.

    Auriez-vous une idée ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
     
    pthread_cond_t autoContinuer = PTHREAD_COND_INITIALIZER;
    pthread_cond_t autoStart = PTHREAD_COND_INITIALIZER;
     
    #define NB_RDV 3
    #define NB_THREADS 9
     
    int iRdv=0;
    pthread_mutex_t emAffichage = PTHREAD_MUTEX_INITIALIZER;//init à 1
    int continuer=0;
    int nbFini=0;
     
    void traitement_principal(){
    	if(iRdv==NB_RDV){
    		iRdv=0;
    		continuer+=1;
    		printf("Thread %lu, je débloques ceux en attente \n",pthread_self());
    		pthread_cond_broadcast(&autoContinuer);
    	}else{
    		continuer+=1;
    	}
    	while(continuer < NB_RDV){
    		printf("Thread %lu, j'attends' \n",pthread_self());
    		pthread_cond_wait(&autoContinuer,&emAffichage);
    	}
    	printf("Thread %lu, je finis mon traitement\n",pthread_self());
    	nbFini++;
    	if(nbFini==NB_RDV){
    		continuer=0;
    	}
    	while(continuer==0){
    		pthread_cond_broadcast(&autoStart);
    	}
    }
     
    void* traitement(){
    	pthread_mutex_lock (&emAffichage);//demande accès
    	while(continuer!=0 && iRdv==0){
    		pthread_cond_wait(&autoStart,&emAffichage);
    	}
    	printf("Thread %lu, je commence mon traitement \n",pthread_self());
    	iRdv+=1;
    	traitement_principal();
    	pthread_mutex_unlock (&emAffichage);//rend accès
    	pthread_exit((void *)NULL);
    }
     
    void thdErreur(int codeErr, char *msgErr, void *codeArret) {
      fprintf(stderr, "%s: %d soit %s \n", msgErr, codeErr, strerror(codeErr));
      pthread_exit(codeArret);
    }
     
    int main(int argc, char const *argv[])
    {
    	int etat;
    	pthread_t idThd[NB_THREADS];
    	for(int i = 0; i <  NB_THREADS; i++){
    		if ((etat = pthread_create(&idThd[i], NULL, traitement,NULL)) != 0)
            thdErreur(etat, "Creation thread avec rdv",NULL);
    	}
    	/* Attendre la fin des threads afficheur car si le thread principal
        - i.e. le main() - se termine, les threads fils crees meurent aussi */
      for (int i = 0; i < NB_THREADS; i++)
        if ((etat = pthread_join(idThd[i], NULL)) != 0)
          thdErreur(etat, "Join threads afficheurs", NULL);
     
      printf ("\nFin de l'execution du thread principal \n");
    	return 0;
    }
    Merci à vous !

  2. #2
    Membre expert
    Inscrit en
    mars 2005
    Messages
    1 072
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 072
    Points : 3 137
    Points
    3 137

    Par défaut

    Pour commencer tu as une boucle infinie à la fin de traitement_principal puisque le thread qui broadcast le signal possède le mutex : aucun autre n'est débloqué tant qu'il ne l'a pas rendu et puisque la valeur de continuer n'est plus jamais modifiée, boum.

    De plus, nbFini est incrémenté et jamais réinitialisé. Ton programme devrait mieux fonctionner avec ceci à la fin de traitement_principal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        if (nbFini == NB_RDV) {
            continuer = 0;
            nbFini = 0;
     
            pthread_cond_broadcast(&autoStart);
        }
    Je soupçonne d'autres possibilités de deadlock mais je n'ai pas beaucoup creusé.


    Accessoirement, attention :

    • pthread_create attend un void *(*)(void *) alors que tu lui fournis un void *(*)(void) (fonction traitement) : un comportement indéterminé s'ensuit ;
    • personnellement je réserve pthread_exit aux cas d'erreur survenant plus profondément dans la pile d'appel et dans la mesure du possible je return proprement depuis le worker principal (la fonction passée à pthread_create). Ceci pour les mêmes raisons que j'évite d'invoquer exit, en tout cas depuis main.

Discussions similaires

  1. Compte admin bloqué sans raison apparente
    Par threshold dans le forum Windows Serveur
    Réponses: 4
    Dernier message: 18/09/2008, 10h35
  2. [D7] [Paradox] Application fermée par XP pro SP2 sans raison apparente
    Par plante20100 dans le forum Bases de données
    Réponses: 9
    Dernier message: 13/09/2007, 13h06
  3. Réponses: 2
    Dernier message: 17/01/2007, 20h23
  4. Pc se bloque sans raisons
    Par madislak dans le forum Ordinateurs
    Réponses: 6
    Dernier message: 22/08/2006, 09h55
  5. Page s'exécutant sans raison apparente
    Par j_bolduc dans le forum ASP
    Réponses: 4
    Dernier message: 23/02/2006, 16h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo