Diff for /rpl/src/interruptions.c between versions 1.30 and 1.209

version 1.30, 2010/08/17 11:59:28 version 1.209, 2023/08/07 17:42:59
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.18    RPL/2 (R) version 4.1.35
   Copyright (C) 1989-2010 Dr. BERTRAND Joël    Copyright (C) 1989-2023 Dr. BERTRAND Joël
   
   This file is part of RPL/2.    This file is part of RPL/2.
   
Line 52  typedef struct liste_chainee_volatile Line 52  typedef struct liste_chainee_volatile
     volatile void                           *donnee;      volatile void                           *donnee;
 } struct_liste_chainee_volatile;  } struct_liste_chainee_volatile;
   
   
 static volatile struct_liste_chainee_volatile   *liste_threads  static volatile struct_liste_chainee_volatile   *liste_threads
         = NULL;          = NULL;
 static volatile struct_liste_chainee_volatile   *liste_threads_surveillance  static volatile struct_liste_chainee_volatile   *liste_threads_surveillance
         = NULL;          = NULL;
   static volatile int                             code_erreur_gsl = 0;
   
   unsigned char                                   *racine_segment;
   
   static void *
   thread_surveillance_signaux(void *argument)
   {
       // Cette fonction est lancée dans un thread créé par processus pour
       // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du
       // signal SIGUSR2. Les processus externes n'envoient plus un signal au
       // processus ou au thread à signaler mais positionnent les informations
       // nécessaires dans la queue des signaux et incrémentent le sémaphore.
       // Le sémaphore est décrémenté lorsque le signal est effectivement traité.
   
       int                                     nombre_signaux_envoyes;
   
       struct_processus                        *s_etat_processus;
   
       struct timespec                         attente;
   
       volatile struct_liste_chainee_volatile  *l_element_courant;
   
       sigset_t                                set;
   
       sigfillset(&set);
       pthread_sigmask(SIG_BLOCK, &set, NULL);
   
       s_etat_processus = (struct_processus *) argument;
   
       for(;;)
       {
           attente.tv_sec = 0;
           attente.tv_nsec = GRANULARITE_us * 1000;
   
           if (sem_wait(semaphore_signalisation) == 0)
           {
               while(sem_wait(semaphore_arret_signalisation) != 0)
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                   }
               }
   
               if ((*s_queue_signaux).requete_arret == d_vrai)
               {
                   sem_post(semaphore_arret_signalisation);
                   sem_post(semaphore_signalisation);
   
                   break;
               }
   
               sem_post(semaphore_signalisation);
   
               nombre_signaux_envoyes = 0;
   
               // Dans un premier temps, on verrouille la queue des signaux
               // affectée au processus courant pour vérifier s'il y a quelque
               // chose à traiter.
   
               while(sem_wait(semaphore_queue_signaux) != 0)
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                   }
               }
   
               if ((*s_queue_signaux).pointeur_lecture !=
                       (*s_queue_signaux).pointeur_ecriture)
               {
                   // Attention : raise() envoit le signal au thread appelant !
                   // kill() l'envoie au processus appelant, donc dans notre
                   // cas à un thread aléatoire du processus, ce qui nous
                   // convient tout à fait puisqu'il s'agit de débloquer les
                   // appels système lents.
   
                   nombre_signaux_envoyes++;
                   kill(getpid(), SIGUSR2);
                   sched_yield();
               }
   
               sem_post(semaphore_queue_signaux);
               sem_post(semaphore_arret_signalisation);
   
               // Dans un second temps, on balaye toutes les queues de signaux
               // des threads du processus courant.
   
               // Attention : l'ordre de verrouillage des mutexes est important
               // pour éviter les conditions bloquantes !
   
               pthread_mutex_lock(&mutex_liste_threads);
   
               l_element_courant = liste_threads;
   
               while(l_element_courant != NULL)
               {
                   if ((*((struct_thread *) (*l_element_courant).donnee)).pid
                           == getpid())
                   {
                       pthread_mutex_lock(&((*(*((struct_thread *)
                               (*l_element_courant).donnee)).s_etat_processus)
                               .mutex_signaux));
   
                       if ((*(*((struct_thread *) (*l_element_courant).donnee))
                               .s_etat_processus).pointeur_signal_ecriture !=
                               (*(*((struct_thread *) (*l_element_courant)
                               .donnee)).s_etat_processus).pointeur_signal_lecture)
                       {
                           nombre_signaux_envoyes++;
                           pthread_kill((*((struct_thread *)
                                   (*l_element_courant).donnee)).tid, SIGUSR2);
                           sched_yield();
                       }
   
                       pthread_mutex_unlock(&((*(*((struct_thread *)
                               (*l_element_courant).donnee)).s_etat_processus)
                               .mutex_signaux));
                   }
   
                   l_element_courant = (*l_element_courant).suivant;
               }
   
               pthread_mutex_unlock(&mutex_liste_threads);
   
               // Nanosleep
   
               if (nombre_signaux_envoyes > 0)
               {
                   nanosleep(&attente, NULL);
               }
           }
           else
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
               }
           }
       }
   
       pthread_exit(NULL);
   }
   
 void  void
 modification_pid_thread_pere(struct_processus *s_etat_processus)  modification_pid_thread_pere(struct_processus *s_etat_processus)
Line 74  modification_pid_thread_pere(struct_proc Line 216  modification_pid_thread_pere(struct_proc
 void  void
 insertion_thread(struct_processus *s_etat_processus, logical1 thread_principal)  insertion_thread(struct_processus *s_etat_processus, logical1 thread_principal)
 {  {
     sigset_t                                    oldset;      int                                         ios;
     sigset_t                                    set;  
   
     volatile struct_liste_chainee_volatile      *l_nouvel_objet;      struct timespec                             attente;
   
     sigfillset(&set);      volatile struct_liste_chainee_volatile      *l_nouvel_objet;
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
     if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))      if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
             == NULL)              == NULL)
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
   
     if (((*l_nouvel_objet).donnee = malloc(sizeof(struct_thread))) == NULL)      if (((*l_nouvel_objet).donnee = malloc(sizeof(struct_thread))) == NULL)
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
Line 108  insertion_thread(struct_processus *s_eta Line 242  insertion_thread(struct_processus *s_eta
     (*((struct_thread *) (*l_nouvel_objet).donnee)).s_etat_processus =      (*((struct_thread *) (*l_nouvel_objet).donnee)).s_etat_processus =
             s_etat_processus;              s_etat_processus;
   
 #   ifndef SEMAPHORES_NOMMES      attente.tv_sec = 0;
     while(sem_wait(&semaphore_liste_threads) == -1)      attente.tv_nsec = GRANULARITE_us * 1000;
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)      while((ios = pthread_mutex_trylock(&mutex_liste_threads)) != 0)
 #   endif  
     {      {
         if (errno != EINTR)          if (ios != EBUSY)
         {          {
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);              (*s_etat_processus).erreur_systeme = d_es_processus;
             sigpending(&set);              return;
           }
   
           if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
           {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
   
           nanosleep(&attente, NULL);
           INCR_GRANULARITE(attente.tv_nsec);
   
           while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
           }
     }      }
   
     (*l_nouvel_objet).suivant = liste_threads;      (*l_nouvel_objet).suivant = liste_threads;
     liste_threads = l_nouvel_objet;      liste_threads = l_nouvel_objet;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
     return;      return;
 }  }
   
Line 149  void Line 288  void
 insertion_thread_surveillance(struct_processus *s_etat_processus,  insertion_thread_surveillance(struct_processus *s_etat_processus,
         struct_descripteur_thread *s_argument_thread)          struct_descripteur_thread *s_argument_thread)
 {  {
     sigset_t                                    oldset;  
     sigset_t                                    set;  
   
     volatile struct_liste_chainee_volatile      *l_nouvel_objet;      volatile struct_liste_chainee_volatile      *l_nouvel_objet;
   
     sigfillset(&set);  
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
     if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))      if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
             == NULL)              == NULL)
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_lock(&mutex_liste_threads_surveillance) != 0)
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     pthread_mutex_lock(&((*s_argument_thread).mutex));      pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references));
     (*s_argument_thread).nombre_references++;      (*s_argument_thread).nombre_references++;
     pthread_mutex_unlock(&((*s_argument_thread).mutex));      pthread_mutex_unlock(&((*s_argument_thread).mutex_nombre_references));
   
     (*l_nouvel_objet).suivant = liste_threads_surveillance;      (*l_nouvel_objet).suivant = liste_threads_surveillance;
     (*l_nouvel_objet).donnee = (void *) s_argument_thread;      (*l_nouvel_objet).donnee = (void *) s_argument_thread;
   
     liste_threads_surveillance = l_nouvel_objet;      liste_threads_surveillance = l_nouvel_objet;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads_surveillance) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
     return;      return;
 }  }
   
 void  void
 retrait_thread(struct_processus *s_etat_processus)  retrait_thread(struct_processus *s_etat_processus)
 {  {
     sigset_t                                oldset;      int                                     ios;
     sigset_t                                set;  
       struct timespec                         attente;
   
     volatile struct_liste_chainee_volatile  *l_element_precedent;      volatile struct_liste_chainee_volatile  *l_element_precedent;
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     sigfillset(&set);      attente.tv_sec = 0;
     pthread_sigmask(SIG_BLOCK, &set, &oldset);      attente.tv_nsec = GRANULARITE_us * 1000;
   
 #   ifndef SEMAPHORES_NOMMES      while((ios = pthread_mutex_trylock(&mutex_liste_threads)) != 0)
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          if (ios != EBUSY)
         {          {
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);              (*s_etat_processus).erreur_systeme = d_es_processus;
             sigpending(&set);              return;
           }
   
           if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
           {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
   
           nanosleep(&attente, NULL);
           INCR_GRANULARITE(attente.tv_nsec);
   
           while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
           }
     }      }
   
     l_element_precedent = NULL;      l_element_precedent = NULL;
Line 256  retrait_thread(struct_processus *s_etat_ Line 379  retrait_thread(struct_processus *s_etat_
   
     if (l_element_courant == NULL)      if (l_element_courant == NULL)
     {      {
 #       ifndef SEMAPHORES_NOMMES          pthread_mutex_unlock(&mutex_liste_threads);
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
Line 277  retrait_thread(struct_processus *s_etat_ Line 393  retrait_thread(struct_processus *s_etat_
         (*l_element_precedent).suivant = (*l_element_courant).suivant;          (*l_element_precedent).suivant = (*l_element_courant).suivant;
     }      }
   
     if (pthread_setspecific(semaphore_fork_processus_courant, NULL) != 0)      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
   
 #       ifndef SEMAPHORES_NOMMES  
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
         return;          return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      // Le thread ne peut plus traiter de signaux explicites. Il convient
     if (sem_post(&semaphore_liste_threads) != 0)      // alors de corriger le sémaphore pour annuler les signaux en attente.
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)      while((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
 #   endif              .pointeur_signal_ecriture != (*(*((struct_thread *)
               (*l_element_courant).donnee)).s_etat_processus)
               .pointeur_signal_lecture)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          while(sem_wait(semaphore_signalisation) != 0)
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
           }
   
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          (*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
         sigpending(&set);                  .pointeur_signal_lecture = ((*(*((struct_thread *)
         return;                  (*l_element_courant).donnee)).s_etat_processus)
                   .pointeur_signal_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX;
     }      }
   
     free((void *) (*l_element_courant).donnee);      free((void *) (*l_element_courant).donnee);
     free((struct_liste_chainee_volatile *) l_element_courant);      free((struct_liste_chainee_volatile *) l_element_courant);
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
     return;      return;
 }  }
   
Line 316  void Line 432  void
 retrait_thread_surveillance(struct_processus *s_etat_processus,  retrait_thread_surveillance(struct_processus *s_etat_processus,
         struct_descripteur_thread *s_argument_thread)          struct_descripteur_thread *s_argument_thread)
 {  {
     sigset_t                                set;  
     sigset_t                                oldset;  
   
     volatile struct_liste_chainee_volatile  *l_element_precedent;      volatile struct_liste_chainee_volatile  *l_element_precedent;
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     sigfillset(&set);      if (pthread_mutex_lock(&mutex_liste_threads_surveillance) != 0)
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     l_element_precedent = NULL;      l_element_precedent = NULL;
Line 357  retrait_thread_surveillance(struct_proce Line 457  retrait_thread_surveillance(struct_proce
   
     if (l_element_courant == NULL)      if (l_element_courant == NULL)
     {      {
 #       ifndef SEMAPHORES_NOMMES          pthread_mutex_unlock(&mutex_liste_threads_surveillance);
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
Line 378  retrait_thread_surveillance(struct_proce Line 471  retrait_thread_surveillance(struct_proce
         (*l_element_precedent).suivant = (*l_element_courant).suivant;          (*l_element_precedent).suivant = (*l_element_courant).suivant;
     }      }
   
     if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)      if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
               != 0)
     {      {
 #       ifndef SEMAPHORES_NOMMES          pthread_mutex_unlock(&mutex_liste_threads_surveillance);
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
Line 400  retrait_thread_surveillance(struct_proce Line 487  retrait_thread_surveillance(struct_proce
   
     if ((*s_argument_thread).nombre_references == 0)      if ((*s_argument_thread).nombre_references == 0)
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES              pthread_mutex_unlock(&mutex_liste_threads_surveillance);
             sem_post(&semaphore_liste_threads);  
 #           else  
             sem_post(semaphore_liste_threads);  
 #           endif  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
   
         pthread_mutex_destroy(&((*s_argument_thread).mutex));          pthread_mutex_destroy(&((*s_argument_thread).mutex));
           pthread_mutex_destroy(&((*s_argument_thread).mutex_nombre_references));
         free(s_argument_thread);          free(s_argument_thread);
     }      }
     else      else
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES              pthread_mutex_unlock(&mutex_liste_threads_surveillance);
             sem_post(&semaphore_liste_threads);  
 #           else  
             sem_post(semaphore_liste_threads);  
 #           endif  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads_surveillance) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     free((struct_liste_chainee_volatile *) l_element_courant);      free((struct_liste_chainee_volatile *) l_element_courant);
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
   
     return;      return;
 }  }
   
 void  void
 verrouillage_threads_concurrents(struct_processus *s_etat_processus)  verrouillage_threads_concurrents(struct_processus *s_etat_processus)
 {  {
       int                                     ios;
   
       struct timespec                         attente;
   
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
 #   ifndef SEMAPHORES_NOMMES      attente.tv_sec = 0;
     while(sem_wait(&semaphore_liste_threads) == -1)      attente.tv_nsec = GRANULARITE_us * 1000;
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)      while((ios = pthread_mutex_trylock(&mutex_liste_threads)) != 0)
 #   endif  
     {      {
         if (errno != EINTR)          if (ios != EBUSY)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
   
           if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
           nanosleep(&attente, NULL);
           INCR_GRANULARITE(attente.tv_nsec);
   
           while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
           }
     }      }
   
     l_element_courant = liste_threads;      l_element_courant = liste_threads;
Line 482  verrouillage_threads_concurrents(struct_ Line 568  verrouillage_threads_concurrents(struct_
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)                  while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)
                     .donnee)).s_etat_processus).semaphore_fork)) == -1)                          .donnee)).s_etat_processus).semaphore_fork)) == -1)
 #           else  #           else
             while(sem_wait((*(*((struct_thread *) (*l_element_courant)                  while(sem_wait((*(*((struct_thread *) (*l_element_courant)
                     .donnee)).s_etat_processus).semaphore_fork) == -1)                          .donnee)).s_etat_processus).semaphore_fork) == -1)
 #           endif  #           endif
             {              {
                 if (errno != EINTR)                  if (errno != EINTR)
Line 517  deverrouillage_threads_concurrents(struc Line 603  deverrouillage_threads_concurrents(struc
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             if (sem_post(&((*(*((struct_thread *)                  if (sem_post(&((*(*((struct_thread *)
                     (*l_element_courant).donnee)).s_etat_processus)                          (*l_element_courant).donnee)).s_etat_processus)
                     .semaphore_fork)) != 0)                          .semaphore_fork)) != 0)
 #           else  #           else
             if (sem_post((*(*((struct_thread *)                  if (sem_post((*(*((struct_thread *)
                     (*l_element_courant).donnee)).s_etat_processus)                          (*l_element_courant).donnee)).s_etat_processus)
                     .semaphore_fork) != 0)                          .semaphore_fork) != 0)
 #           endif  #           endif
             {              {
 #               ifndef SEMAPHORES_NOMMES                  if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
                 if (sem_post(&semaphore_liste_threads) != 0)  
                 {  
                     (*s_etat_processus).erreur_systeme = d_es_processus;  
                     return;  
                 }  
 #               else  
                 if (sem_post(semaphore_liste_threads) != 0)  
                 {                  {
                     (*s_etat_processus).erreur_systeme = d_es_processus;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     return;                      return;
                 }                  }
 #               endif  
   
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 return;                  return;
Line 548  deverrouillage_threads_concurrents(struc Line 626  deverrouillage_threads_concurrents(struc
         l_element_courant = (*l_element_courant).suivant;          l_element_courant = (*l_element_courant).suivant;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
Line 566  liberation_threads(struct_processus *s_e Line 640  liberation_threads(struct_processus *s_e
 {  {
     logical1                                    suppression_variables_partagees;      logical1                                    suppression_variables_partagees;
   
     sigset_t                                    oldset;  
     sigset_t                                    set;  
   
     struct_descripteur_thread                   *s_argument_thread;      struct_descripteur_thread                   *s_argument_thread;
   
     struct_processus                            *candidat;      struct_processus                            *candidat;
   
     unsigned long                               i;      struct_liste_variables_partagees            *l_element_partage_courant;
       struct_liste_variables_partagees            *l_element_partage_suivant;
   
       struct_liste_variables_statiques            *l_element_statique_courant;
       struct_liste_variables_statiques            *l_element_statique_suivant;
   
       integer8                                    i;
   
     void                                        *element_candidat;      void                                        *element_candidat;
     void                                        *element_courant;      void                                        *element_courant;
Line 582  liberation_threads(struct_processus *s_e Line 659  liberation_threads(struct_processus *s_e
     volatile struct_liste_chainee_volatile      *l_element_courant;      volatile struct_liste_chainee_volatile      *l_element_courant;
     volatile struct_liste_chainee_volatile      *l_element_suivant;      volatile struct_liste_chainee_volatile      *l_element_suivant;
   
     sigfillset(&set);      if (pthread_mutex_lock(&mutex_liste_threads) == -1)
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     l_element_courant = liste_threads;      l_element_courant = liste_threads;
Line 627  liberation_threads(struct_processus *s_e Line 693  liberation_threads(struct_processus *s_e
             close((*s_etat_processus).pipe_injections);              close((*s_etat_processus).pipe_injections);
             close((*s_etat_processus).pipe_nombre_injections);              close((*s_etat_processus).pipe_nombre_injections);
             close((*s_etat_processus).pipe_interruptions);              close((*s_etat_processus).pipe_interruptions);
             close((*s_etat_processus).pipe_nombre_objets_attente);              close((*s_etat_processus).pipe_nombre_elements_attente);
             close((*s_etat_processus).pipe_nombre_interruptions_attente);  
   
             liberation(s_etat_processus, (*s_etat_processus).at_exit);              liberation(s_etat_processus, (*s_etat_processus).at_exit);
   
Line 676  liberation_threads(struct_processus *s_e Line 741  liberation_threads(struct_processus *s_e
                 s_argument_thread = (struct_descripteur_thread *)                  s_argument_thread = (struct_descripteur_thread *)
                         (*((struct_liste_chainee *) element_courant)).donnee;                          (*((struct_liste_chainee *) element_courant)).donnee;
   
                 if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)                  if (pthread_mutex_lock(&((*s_argument_thread)
                           .mutex_nombre_references)) != 0)
                 {                  {
                     (*s_etat_processus).erreur_systeme = d_es_processus;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     sem_post(&semaphore_liste_threads);                      pthread_mutex_unlock(&mutex_liste_threads);
                     return;                      return;
                 }                  }
   
Line 695  liberation_threads(struct_processus *s_e Line 761  liberation_threads(struct_processus *s_e
                     close((*s_argument_thread).pipe_acquittement[1]);                      close((*s_argument_thread).pipe_acquittement[1]);
                     close((*s_argument_thread).pipe_injections[1]);                      close((*s_argument_thread).pipe_injections[1]);
                     close((*s_argument_thread).pipe_nombre_injections[1]);                      close((*s_argument_thread).pipe_nombre_injections[1]);
                     close((*s_argument_thread).pipe_nombre_objets_attente[0]);                      close((*s_argument_thread).pipe_nombre_elements_attente[0]);
                     close((*s_argument_thread).pipe_interruptions[0]);                      close((*s_argument_thread).pipe_interruptions[0]);
                     close((*s_argument_thread)  
                             .pipe_nombre_interruptions_attente[0]);  
   
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          pthread_mutex_unlock(&mutex_liste_threads);
                         return;                          return;
                     }                      }
   
                     pthread_mutex_destroy(&((*s_argument_thread).mutex));                      pthread_mutex_destroy(&((*s_argument_thread).mutex));
                       pthread_mutex_destroy(&((*s_argument_thread)
                               .mutex_nombre_references));
   
                     if ((*s_argument_thread).processus_detache == d_faux)                      if ((*s_argument_thread).processus_detache == d_faux)
                     {                      {
Line 723  liberation_threads(struct_processus *s_e Line 789  liberation_threads(struct_processus *s_e
                 }                  }
                 else                  else
                 {                  {
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          pthread_mutex_unlock(&mutex_liste_threads);
                         return;                          return;
                     }                      }
                 }                  }
Line 796  liberation_threads(struct_processus *s_e Line 862  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             for(i = 0; i < (*s_etat_processus).nombre_variables; i++)  
             {  
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
   
                 // Les variables de niveau 0 sont des définitions qui  
                 // ne sont pas copiées entre threads.  
                 if ((*s_etat_processus).s_liste_variables[i].niveau > 0)  
                 {  
                     liberation(s_etat_processus,  
                             (*s_etat_processus).s_liste_variables[i].objet);  
                 }  
   
                 free((*s_etat_processus).s_liste_variables[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables);  
   
             for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)  
             {  
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
   
                 liberation(s_etat_processus, (*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet);  
                 free((*s_etat_processus).s_liste_variables_statiques[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables_statiques);  
   
             // Ne peut être effacé qu'une seule fois              // Ne peut être effacé qu'une seule fois
             if (suppression_variables_partagees == d_faux)              if (suppression_variables_partagees == d_faux)
             {              {
                 suppression_variables_partagees = d_vrai;                  suppression_variables_partagees = d_vrai;
   
                 for(i = 0; i < (*(*s_etat_processus)                  liberation_arbre_variables_partagees(s_etat_processus,
                         .s_liste_variables_partagees).nombre_variables; i++)                          (*(*s_etat_processus).s_arbre_variables_partagees));
                 {                  (*(*s_etat_processus).s_arbre_variables_partagees) = NULL;
                     pthread_mutex_trylock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
                     pthread_mutex_unlock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
   
                     liberation(s_etat_processus, (*(*s_etat_processus)                  l_element_partage_courant = (*(*s_etat_processus)
                             .s_liste_variables_partagees).table[i].objet);                          .l_liste_variables_partagees);
                     free((*(*s_etat_processus).s_liste_variables_partagees)  
                             .table[i].nom);  
                 }  
   
                 if ((*(*s_etat_processus).s_liste_variables_partagees).table                  while(l_element_partage_courant != NULL)
                         != NULL)  
                 {                  {
                     free((struct_variable_partagee *) (*(*s_etat_processus)                      l_element_partage_suivant =
                             .s_liste_variables_partagees).table);                              (*l_element_partage_courant).suivant;
                       free(l_element_partage_courant);
                       l_element_partage_courant = l_element_partage_suivant;
                 }                  }
   
                 pthread_mutex_trylock(&((*(*s_etat_processus)                  (*(*s_etat_processus).l_liste_variables_partagees) = NULL;
                         .s_liste_variables_partagees).mutex));              }
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_partagees).mutex));              liberation_arbre_variables(s_etat_processus,
                       (*s_etat_processus).s_arbre_variables, d_faux);
   
               l_element_statique_courant = (*s_etat_processus)
                       .l_liste_variables_statiques;
   
               while(l_element_statique_courant != NULL)
               {
                   l_element_statique_suivant =
                       (*l_element_statique_courant).suivant;
                   free(l_element_statique_courant);
                   l_element_statique_courant = l_element_statique_suivant;
             }              }
   
             element_courant = (*s_etat_processus).l_base_pile;              element_courant = (*s_etat_processus).l_base_pile;
Line 1321  liberation_threads(struct_processus *s_e Line 1356  liberation_threads(struct_processus *s_e
             liberation_allocateur(s_etat_processus);              liberation_allocateur(s_etat_processus);
   
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             sem_post(&((*s_etat_processus).semaphore_fork));                  sem_post(&((*s_etat_processus).semaphore_fork));
             sem_destroy(&((*s_etat_processus).semaphore_fork));                  sem_destroy(&((*s_etat_processus).semaphore_fork));
 #           else  #           else
             sem_post((*s_etat_processus).semaphore_fork);                  sem_post((*s_etat_processus).semaphore_fork);
             sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork);                  sem_close((*s_etat_processus).semaphore_fork);
 #           endif  #           endif
   
             free(s_etat_processus);              liberation_contexte_cas(s_etat_processus);
               liberation_allocateur_buffer(s_etat_processus);
               sys_free(s_etat_processus);
   
             s_etat_processus = candidat;              s_etat_processus = candidat;
         }          }
Line 1343  liberation_threads(struct_processus *s_e Line 1380  liberation_threads(struct_processus *s_e
   
     liste_threads = NULL;      liste_threads = NULL;
   
       if (pthread_mutex_unlock(&mutex_liste_threads) == -1)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
       if (pthread_mutex_lock(&mutex_liste_threads_surveillance) == -1)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
     l_element_courant = liste_threads_surveillance;      l_element_courant = liste_threads_surveillance;
   
     while(l_element_courant != NULL)      while(l_element_courant != NULL)
Line 1350  liberation_threads(struct_processus *s_e Line 1399  liberation_threads(struct_processus *s_e
         s_argument_thread = (struct_descripteur_thread *)          s_argument_thread = (struct_descripteur_thread *)
                 (*l_element_courant).donnee;                  (*l_element_courant).donnee;
   
         if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
                   != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             sem_post(&semaphore_liste_threads);              pthread_mutex_unlock(&mutex_liste_threads_surveillance);
             return;              return;
         }          }
   
Line 1369  liberation_threads(struct_processus *s_e Line 1419  liberation_threads(struct_processus *s_e
             close((*s_argument_thread).pipe_acquittement[1]);              close((*s_argument_thread).pipe_acquittement[1]);
             close((*s_argument_thread).pipe_injections[1]);              close((*s_argument_thread).pipe_injections[1]);
             close((*s_argument_thread).pipe_nombre_injections[1]);              close((*s_argument_thread).pipe_nombre_injections[1]);
             close((*s_argument_thread).pipe_nombre_objets_attente[0]);              close((*s_argument_thread).pipe_nombre_elements_attente[0]);
             close((*s_argument_thread).pipe_interruptions[0]);              close((*s_argument_thread).pipe_interruptions[0]);
             close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);  
   
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  pthread_mutex_unlock(&mutex_liste_threads_surveillance);
                 return;                  return;
             }              }
   
             pthread_mutex_destroy(&((*s_argument_thread).mutex));              pthread_mutex_destroy(&((*s_argument_thread).mutex));
               pthread_mutex_destroy(&((*s_argument_thread)
                       .mutex_nombre_references));
   
             if ((*s_argument_thread).processus_detache == d_faux)              if ((*s_argument_thread).processus_detache == d_faux)
             {              {
Line 1394  liberation_threads(struct_processus *s_e Line 1446  liberation_threads(struct_processus *s_e
         }          }
         else          else
         {          {
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  pthread_mutex_unlock(&mutex_liste_threads_surveillance);
                 return;                  return;
             }              }
         }          }
Line 1409  liberation_threads(struct_processus *s_e Line 1462  liberation_threads(struct_processus *s_e
   
     liste_threads_surveillance = NULL;      liste_threads_surveillance = NULL;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads_surveillance) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
     return;      return;
 }  }
   
Line 1432  recherche_thread(pid_t pid, pthread_t ti Line 1478  recherche_thread(pid_t pid, pthread_t ti
   
     struct_processus                            *s_etat_processus;      struct_processus                            *s_etat_processus;
   
       if (pthread_mutex_lock(&mutex_liste_threads) != 0)
       {
           return(NULL);
       }
   
     l_element_courant = liste_threads;      l_element_courant = liste_threads;
   
     while(l_element_courant != NULL)      while(l_element_courant != NULL)
Line 1452  recherche_thread(pid_t pid, pthread_t ti Line 1503  recherche_thread(pid_t pid, pthread_t ti
          * Le processus n'existe plus. On ne distribue aucun signal.           * Le processus n'existe plus. On ne distribue aucun signal.
          */           */
   
           pthread_mutex_unlock(&mutex_liste_threads);
         return(NULL);          return(NULL);
     }      }
   
     s_etat_processus = (*((struct_thread *)      s_etat_processus = (*((struct_thread *)
             (*l_element_courant).donnee)).s_etat_processus;              (*l_element_courant).donnee)).s_etat_processus;
   
       if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
       {
           return(NULL);
       }
   
     return(s_etat_processus);      return(s_etat_processus);
 }  }
   
 static logical1  static struct_processus *
 recherche_thread_principal(pid_t pid, pthread_t *thread)  recherche_thread_principal(pid_t pid)
 {  {
     volatile struct_liste_chainee_volatile      *l_element_courant;      volatile struct_liste_chainee_volatile      *l_element_courant;
   
Line 1486  recherche_thread_principal(pid_t pid, pt Line 1543  recherche_thread_principal(pid_t pid, pt
          * Le processus n'existe plus. On ne distribue aucun signal.           * Le processus n'existe plus. On ne distribue aucun signal.
          */           */
   
         return(d_faux);          return(NULL);
     }      }
   
     (*thread) = (*((struct_thread *) (*l_element_courant).donnee)).tid;      return((*((struct_thread *) (*l_element_courant).donnee))
               .s_etat_processus);
     return(d_vrai);  
 }  }
   
   
Line 1512  recherche_thread_principal(pid_t pid, pt Line 1568  recherche_thread_principal(pid_t pid, pt
 // les sémaphores sont déjà bloqués par un gestionnaire de signal.  // les sémaphores sont déjà bloqués par un gestionnaire de signal.
   
 static inline void  static inline void
 verrouillage_gestionnaire_signaux()  verrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 {  {
     int         semaphore;      return;
   
     sigset_t    oldset;  
     sigset_t    set;  
   
     sem_t       *sem;  
   
     if ((sem = pthread_getspecific(semaphore_fork_processus_courant))  #   ifndef SEMAPHORES_NOMMES
             != NULL)      if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
   #   else
       if (sem_post((*s_etat_processus).semaphore_fork) != 0)
   #   endif
     {      {
         if (sem_post(sem) != 0)          BUG(1, uprintf("Lock error !\n"));
         {          return;
             BUG(1, uprintf("Lock error !\n"));  
             return;  
         }  
     }      }
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !      return;
   }
   
     sigfillset(&set);  static inline void
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
   {
       return;
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)      while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
 #   else  #   else
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)      while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
 #   endif  #   endif
     {      {
         if (errno != EINTR)          if (errno != EINTR)
         {          {
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));              BUG(1, uprintf("Unlock error !\n"));
             return;              return;
         }          }
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      return;
     if (sem_post(&semaphore_gestionnaires_signaux) == -1)  }
 #   else  
     if (sem_post(semaphore_gestionnaires_signaux) == -1)  /*
 #   endif  ================================================================================
     Fonctions de gestion des signaux dans les threads.
   
     Lorsqu'un processus reçoit un signal, il appelle le gestionnaire de signal
     associé qui ne fait qu'envoyer au travers de write() le signal
     reçus dans un pipe. Un second thread est bloqué sur ce pipe et
     effectue le traitement adéquat pour le signal donné.
   ================================================================================
   */
   
   #define test_signal(signal) \
       if (signal_test == SIGTEST) { signal_test = signal; return; }
   
   static int          pipe_signaux;
   
   logical1
   lancement_thread_signaux(struct_processus *s_etat_processus)
   {
       pthread_attr_t                  attributs;
   
       if (pipe((*s_etat_processus).pipe_signaux) != 0)
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Lock error !\n"));          return(d_erreur);
         return;  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      pipe_signaux = (*s_etat_processus).pipe_signaux[1];
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   else      if (pthread_attr_init(&attributs) != 0)
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Lock error !\n"));          return(d_erreur);
         return;  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
     if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0)  
 #   else  
     if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Unlock error !\n"));          return(d_erreur);
         return;  
     }      }
   
     if (semaphore == 1)      if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
               thread_signaux, s_etat_processus) != 0)
     {      {
         // Le semaphore ne peut être pris par le thread qui a appelé          (*s_etat_processus).erreur_systeme = d_es_processus;
         // le gestionnaire de signal car le signal est bloqué par ce thread          return(d_erreur);
         // dans les zones critiques. Ce sémaphore ne peut donc être bloqué que      }
         // par un thread concurrent. On essaye donc de le bloquer jusqu'à  
         // ce que ce soit possible.  
   
 #       ifndef SEMAPHORES_NOMMES      if (pthread_attr_destroy(&attributs) != 0)
         while(sem_trywait(&semaphore_liste_threads) == -1)      {
 #       else          (*s_etat_processus).erreur_systeme = d_es_processus;
         while(sem_trywait(semaphore_liste_threads) == -1)          return(d_erreur);
 #       endif      }
         {  
             if ((errno != EINTR) && (errno != EAGAIN))  
             {  
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
   
                 while(sem_wait(sem) == -1)      return(d_absence_erreur);
                 {  }
                     if (errno != EINTR)  
                     {  
                         BUG(1, uprintf("Lock error !\n"));  
                         return;  
                     }  
                 }  
   
                 BUG(1, uprintf("Lock error !\n"));  logical1
                 return;  arret_thread_signaux(struct_processus *s_etat_processus)
             }  {
       unsigned char       signal;
       ssize_t             n;
   
       signal = (unsigned char ) (rpl_sigmax & 0xFF);
   
             sched_yield();      do
       {
           n = write_atomic(s_etat_processus, (*s_etat_processus).pipe_signaux[1],
                   &signal, sizeof(signal));
   
           if (n < 0)
           {
               return(d_erreur);
         }          }
     }      } while(n != 1);
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);      pthread_join((*s_etat_processus).thread_signaux, NULL);
     sigpending(&set);  
   
     return;      close((*s_etat_processus).pipe_signaux[1]);
       return(d_absence_erreur);
 }  }
   
 static inline void  void *
 deverrouillage_gestionnaire_signaux()  thread_signaux(void *argument)
 {  {
     int         semaphore;      int                     *pipe;
   
     sem_t       *sem;      sigset_t                masque;
   
     sigset_t    oldset;      struct pollfd           fds;
     sigset_t    set;  
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !      struct_processus        *s_etat_processus;
   
     sigfillset(&set);      unsigned char           signal;
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES      s_etat_processus = (struct_processus *) argument;
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)      pipe = (*s_etat_processus).pipe_signaux;
 #   else      fds.fd = pipe[0];
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)      fds.events = POLLIN;
 #   endif  
     {  
         if (errno != EINTR)  
         {  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }  
     }  
   
 #   ifndef SEMAPHORES_NOMMES      sigfillset(&masque);
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)      pthread_sigmask(SIG_BLOCK, &masque, NULL);
 #   else  
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   endif  
     {  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         BUG(1, uprintf("Unlock error !\n"));  
         return;  
     }  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_gestionnaires_signaux) == -1)  
 #   else  
     while(sem_wait(semaphore_gestionnaires_signaux) == -1)  
 #   endif  
     {  
         if (errno != EINTR)  
         {  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }  
     }  
   
 #   ifndef SEMAPHORES_NOMMES      do
     if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0)  
 #   else  
     if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          fds.revents = 0;
         BUG(1, uprintf("Unlock error !\n"));  
         return;  
     }  
   
     if ((sem = pthread_getspecific(semaphore_fork_processus_courant))          while(poll(&fds, 1, -1) == -1)
             != NULL)  
     {  
         while(sem_wait(sem) == -1)  
         {          {
             if (errno != EINTR)              if (errno != EINTR)
             {              {
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);                  close((*s_etat_processus).pipe_signaux[0]);
                 BUG(1, uprintf("Unlock error !\n"));                  pthread_exit(NULL);
                 return;  
             }              }
         }          }
     }  
   
     if (semaphore == 1)          if (read_atomic(s_etat_processus, fds.fd, &signal, 1) != 1)
     {  
 #       ifndef SEMAPHORES_NOMMES  
         if (sem_post(&semaphore_liste_threads) != 0)  
 #       else  
         if (sem_post(semaphore_liste_threads) != 0)  
 #       endif  
         {          {
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);              close((*s_etat_processus).pipe_signaux[0]);
               pthread_exit(NULL);
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }          }
     }  
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);          if (signal != (0xFF & rpl_sigmax))
     sigpending(&set);          {
               envoi_signal_processus(getpid(), signal, d_faux);
               // Un signal SIGUSR2 est envoyé par le thread de surveillance
               // des signaux jusqu'à ce que les signaux soient tous traités.
           }
       } while(signal != (0xFF & rpl_sigmax));
   
     return;      close((*s_etat_processus).pipe_signaux[0]);
       pthread_exit(NULL);
 }  }
   
 #ifdef _BROKEN_SIGINFO  
   
 static int              *fifos;  static inline void
 static int              segment;  _write(int fd, const void *buf, size_t count)
 static int              segment_mutexes;  {
 static int              longueur_queue;      ssize_t         ios;
 static int              nombre_queues;  
   
 static pthread_mutex_t  *mutexes;      while((ios = write(fd, buf, count)) == -1)
       {
           if (errno != EINTR)
           {
               break;
           }
       }
   
       return;
   }
   
 static unsigned char    *chemin = NULL;  
   
 unsigned char *  // Récupération des signaux
 nom_segment(unsigned char *chemin, pid_t pid)  // - SIGINT  (arrêt au clavier)
   // - SIGTERM (signal d'arrêt en provenance du système)
   
   void
   interruption1(int signal)
 {  {
     unsigned char               *fichier;      unsigned char       signal_tronque;
   
     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *      test_signal(signal);
             sizeof(unsigned char))) == NULL)  
       switch(signal)
     {      {
         return(NULL);          case SIGINT:
     }              signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
               break;
   
     sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);          case SIGTERM:
               signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
               break;
   
     return(fichier);          case SIGUSR1:
               signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
               break;
   
           default:
               // SIGUSR2
               break;
       }
   
       return;
 }  }
   
 unsigned char *  // Récupération des signaux
 nom_segment_mutexes(unsigned char *chemin, pid_t pid)  // - SIGFSTP
   //
   // ATTENTION :
   // Le signal SIGFSTP provient de la mort du processus de contrôle.
   // Sous certains systèmes (Linux...), la mort du terminal de contrôle
   // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
   // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
   // non initialisée (pointeur NULL) issue de TERMIO.
   
   void
   interruption2(int signal)
 {  {
     unsigned char               *fichier;      unsigned char       signal_tronque;
   
     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *      test_signal(signal);
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "%s/RPL-SIGMUTEXES-%d", chemin, (int) pid);      signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
       _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
   
     return(fichier);      return;
 }  }
   
 int  void
 queue_de_signal(int signal)  interruption3(int signal)
 {  {
     switch(signal)      // Si on passe par ici, c'est qu'il est impossible de récupérer
       // l'erreur d'accès à la mémoire. On sort donc du programme quitte à
       // ce qu'il reste des processus orphelins.
   
       unsigned char       message_1[] = "+++System : Uncaught access violation\n"
                                   "+++System : Aborting !\n";
       unsigned char       message_2[] = "+++System : Stack overflow\n"
                                   "+++System : Aborting !\n";
   
       test_signal(signal);
   
       if (pid_processus_pere == getpid())
     {      {
         case SIGINT:          kill(pid_processus_pere, SIGUSR1);
             return(0);  
         case SIGTSTP:  
             return(1);  
         case SIGCONT:  
             return(2);  
         case SIGURG:  
             return(3);  
         case SIGPIPE:  
             return(4);  
         case SIGALRM:  
             return(5);  
         case SIGFSTOP:  
             return(6);  
         case SIGSTART:  
             return(7);  
         case SIGINJECT:  
             return(8);  
         case SIGABORT:  
             return(9);  
         case SIGFABORT:  
             return(10);  
     }      }
   
     return(-1);  #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
       if (signal != SIGUSR2)
       {
           write(STDERR_FILENO, message_1, strlen(message_1));
       }
       else
       {
           write(STDERR_FILENO, message_2, strlen(message_2));
       }
   
   #   pragma GCC diagnostic pop
   
       _exit(EXIT_FAILURE);
 }  }
   
   // Récupération des signaux
   // - SIGHUP
   
 void  void
 creation_fifos_signaux(struct_processus *s_etat_processus)  interruption4(int signal)
 {  {
     file                            *desc;      unsigned char       signal_tronque;
   
     int                             i;      test_signal(signal);
   
     key_t                           clef;      signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
       _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
   
     pthread_mutexattr_t             attributs_mutex;      return;
   }
   
     unsigned char                   *nom;  // Récupération des signaux
   // - SIGPIPE
   
     /*  void
      * Signaux utilisés  interruption5(int signal)
      * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP,  {
      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT      unsigned char       message[] = "+++System : SIGPIPE\n"
      */                                  "+++System : Aborting !\n";
       unsigned char       signal_tronque;
   
     // Création d'un segment de données associé au PID du processus courant      test_signal(signal);
   
     chemin = (*s_etat_processus).chemin_fichiers_temporaires;  #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,      if (pid_processus_pere == getpid())
             getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
         return;          _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     }      }
   
     /*      write(STDERR_FILENO, message, strlen(message));
      * Structure d'une queue  
      * 0 : pointeur en lecture sur le premier emplacement libre (int)  
      * 1 : pointeur en écriture sur le premier emplacement à lire (int)  
      * 2 : longueur de la queue (int)  
      * 3 : éléments restants (int)  
      * 4 à 4 + (2) : queue (int)  
      * 5 : mutex  
      */  
   
     nombre_queues = 11;  #   pragma GCC diagnostic pop
     longueur_queue = 256;  
   
     if ((desc = fopen(nom, "w")) == NULL)      return;
     {  }
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;  
         return;  inline static void
     }  signal_alrm(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     fclose(desc);      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((clef = ftok(nom, 1)) == -1)      if (pid == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Si pid est égal à getpid(), le signal à traiter est issu
         return;          // du même processus que celui qui va le traiter, mais d'un thread
     }          // différent.
   
     free(nom);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     if ((segment = shmget(clef,          if ((*s_etat_processus).pid_processus_pere != getpid())
             nombre_queues * (longueur_queue + 4) * sizeof(int),          {
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)              // On n'est pas dans le processus père, on remonte le signal.
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigalrm, d_faux);
           }
           else
           {
               // On est dans le processus père, on effectue un arrêt d'urgence.
               (*s_etat_processus).var_volatile_alarme = -1;
               (*s_etat_processus).var_volatile_requete_arret = -1;
           }
       }
       else
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Le signal est issu d'un processus différent. On recherche le
         return;          // thread principal pour remonter le signal.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
           }
     }      }
   
     fifos = shmat(segment, NULL, 0);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
     if (((void *) fifos) == ((void *) -1))  inline static void
     {  signal_term(struct_processus *s_etat_processus, pid_t pid)
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  {
         return;      struct_processus        *s_thread_principal;
     }      pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
   
     for(i = 0; i < nombre_queues; i++)      verrouillage_gestionnaire_signaux(s_etat_processus);
     {  
         fifos[(i * (longueur_queue + 4))] = 0;  
         fifos[(i * (longueur_queue + 4)) + 1] = 0;  
         fifos[(i * (longueur_queue + 4)) + 2] = longueur_queue;  
         fifos[(i * (longueur_queue + 4)) + 3] = longueur_queue;  
     }  
   
     if ((nom = nom_segment_mutexes((*s_etat_processus)      if (pid == getpid())
             .chemin_fichiers_temporaires, getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         return;          {
     }              printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
           if ((*s_etat_processus).pid_processus_pere != getpid())
           {
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigterm, d_faux);
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
               pthread_mutex_lock(&exclusion);
   
     if ((desc = fopen(nom, "w")) == NULL)              if ((*s_etat_processus).var_volatile_requete_arret == -1)
               {
                   deverrouillage_gestionnaire_signaux(s_etat_processus);
                   pthread_mutex_unlock(&exclusion);
                   return;
               }
   
               (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
               pthread_mutex_unlock(&exclusion);
           }
       }
       else
     {      {
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;          if ((s_thread_principal = recherche_thread_principal(getpid()))
         return;                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigterm);
           }
     }      }
   
     fclose(desc);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   inline static void
   signal_int(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
       pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((clef = ftok(nom, 1)) == -1)      if (pid == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         return;          {
     }              printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
           if ((*s_etat_processus).pid_processus_pere != getpid())
           {
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigint, d_faux);
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
     free(nom);              pthread_mutex_lock(&exclusion);
   
     if ((segment_mutexes = shmget(clef,              if ((*s_etat_processus).var_volatile_requete_arret == -1)
             nombre_queues * sizeof(pthread_mutex_t),              {
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)                  deverrouillage_gestionnaire_signaux(s_etat_processus);
                   pthread_mutex_unlock(&exclusion);
                   return;
               }
   
               if ((*s_etat_processus).langue == 'F')
               {
                   printf("+++Interruption\n");
               }
               else
               {
                   printf("+++Interrupt\n");
               }
   
               fflush(stdout);
   
               (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
               pthread_mutex_unlock(&exclusion);
           }
       }
       else
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if ((s_thread_principal = recherche_thread_principal(getpid()))
         return;                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigint);
           }
     }      }
   
     mutexes = shmat(segment_mutexes, NULL, 0);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   static inline void
   signal_tstp(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if (((void *) mutexes) == ((void *) -1))      if (pid == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          /*
         return;           *  0 => fonctionnement normal
            * -1 => requête
            *  1 => requête acceptée en attente de traitement
            */
   
           if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
           if ((*s_etat_processus).var_volatile_processus_pere == 0)
           {
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigtstp, d_faux);
           }
           else
           {
               (*s_etat_processus).var_volatile_requete_arret2 = -1;
           }
     }      }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
     /*          if ((s_thread_principal = recherche_thread_principal(getpid()))
      * Création et initialisation d'un mutex par queue. Ce mutex n'est pas                  != NULL)
      * dans le premier segment parce qu'il peut y avoir des problèmes          {
      * d'alignements sur certaines architectures.              envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
      */          }
       }
   
     pthread_mutexattr_init(&attributs_mutex);      deverrouillage_gestionnaire_signaux(s_etat_processus);
     pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_NORMAL);      return;
   }
   
     for(i = 0; i < nombre_queues; i++)  static void
   sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
   {
       switch((*((volatile int *) arg1)))
     {      {
         pthread_mutex_init(&(mutexes[i]), &attributs_mutex);          case 1:
               longjmp(contexte_ecriture, -1);
               break;
   
           case 2:
               longjmp(contexte_impression, -1);
               break;
     }      }
   
     pthread_mutexattr_destroy(&attributs_mutex);  
     return;      return;
 }  }
   
   #ifdef HAVE_SIGSEGV_RECOVERY
 void  void
 liberation_fifos_signaux(struct_processus *s_etat_processus)  interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
 {  {
     if (shmdt(fifos) == -1)      if ((urgence == 0) && (routine_recursive != 0))
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // On peut tenter de récupérer le dépassement de pile. Si la variable
         return;          // 'routine_recursive' est non nulle, on récupère l'erreur.
     }  
   
     if (shmdt(mutexes) == -1)          sigsegv_leave_handler(sortie_interruption_depassement_pile,
     {                  (void *) &routine_recursive, NULL, NULL);
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }      }
   
       // Ici, la panique est totale et il vaut mieux quitter l'application.
       interruption3(SIGUSR2);
     return;      return;
 }  }
   #endif
   
 void  int
 destruction_fifos_signaux(struct_processus *s_etat_processus)  interruption_violation_access(void *adresse_fautive, int gravite)
 {  {
     int                 i;      unsigned char       message[] = "+++System : Trying to catch access "
     unsigned char       *nom;                                  "violation\n";
   
     if (shmdt(fifos) == -1)      static int          compteur_erreur = 0;
   
       if ((gravite == 0) && (routine_recursive != 0))
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Il peut s'agir d'un dépassement de pile.
         return;  
   #       ifdef HAVE_SIGSEGV_RECOVERY
               sigsegv_leave_handler(sortie_interruption_depassement_pile,
                       (void *) &routine_recursive, NULL, NULL);
   #       else
               sortie_interruption_depassement_pile((void *) &routine_recursive,
                       NULL, NULL);
   #       endif
     }      }
   
     if (shmctl(segment, IPC_RMID, 0) == -1)      // On est dans une bonne vieille violation d'accès. On essaie
       // de fermer au mieux l'application.
   
       compteur_erreur++;
   
       if (compteur_erreur >= 2)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Erreurs multiples, on arrête l'application.
         return;          interruption3(SIGSEGV);
           return(0);
     }      }
   
     for(i = 0; i < nombre_queues; i++)  #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
       write(STDERR_FILENO, message, strlen(message));
   
   #   pragma GCC diagnostic pop
   
       if (pid_processus_pere == getpid())
     {      {
         pthread_mutex_destroy(&(mutexes[i]));          longjmp(contexte_initial, -1);
           return(1);
     }      }
       else
     if (shmdt(mutexes) == -1)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          longjmp(contexte_processus, -1);
         return;          return(1);
     }      }
   
     if (shmctl(segment_mutexes, IPC_RMID, 0) == -1)      // On renvoie 0 parce qu'on décline toute responsabilité quant à la
       // suite des événements...
       return(0);
   }
   
   // Traitement de rpl_sigstart
   
   static inline void
   signal_start(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).demarrage_fils = d_vrai;
         return;  
     }      }
       else
     if ((nom = nom_segment_mutexes((*s_etat_processus)  
             .chemin_fichiers_temporaires, getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Envoi d'un signal au thread maître du groupe.
         return;  
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigstart);
           }
     }      }
   
     unlink(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
     free(nom);      return;
   }
   
   // Traitement de rpl_sigcont
   
   static inline void
   signal_cont(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,      if (pid == getpid())
             getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).redemarrage_processus = d_vrai;
         return;  
     }      }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
     unlink(nom);          if ((s_thread_principal = recherche_thread_principal(getpid()))
     free(nom);                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigcont);
           }
       }
   
       deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 int  // Traitement de rpl_sigstop
 queue_in(pid_t pid, int signal)  
   static inline void
   signal_stop(struct_processus *s_etat_processus, pid_t pid)
 {  {
     int             *base;      struct_processus        *s_thread_principal;
     int             *buffer;  
     int             *projection_fifos;      verrouillage_gestionnaire_signaux(s_etat_processus);
     int             queue;  
     int             identifiant;      if (pid == getpid())
       {
           if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
           /*
            * var_globale_traitement_retarde_stop :
            *  0 -> traitement immédiat
            *  1 -> traitement retardé (aucun signal reçu)
            * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
            */
   
     key_t           clef;          if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
           {
               (*s_etat_processus).var_volatile_requete_arret = -1;
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
           }
       }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
     pthread_mutex_t *projection_mutexes;          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigstop);
           }
       }
   
     unsigned char   *nom;      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
     queue = queue_de_signal(signal);  // Traitement de rpl_siginject
   
     // Ouverture des projections  static inline void
   signal_inject(struct_processus *s_etat_processus, pid_t pid)
   {
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((nom = nom_segment(chemin, pid)) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         return(-1);          deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
     }      }
   
     if ((clef = ftok(nom, 1)) == -1)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         free(nom);          printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
         return(-1);                  (unsigned long long) pthread_self());
           fflush(stdout);
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   
     while((identifiant = shmget(clef,  static inline void
             nombre_queues * (longueur_queue + 4) * sizeof(int),  signal_urg(struct_processus *s_etat_processus, pid_t pid)
             S_IRUSR | S_IWUSR)) == -1);  {
       struct_processus        *s_thread_principal;
   
     projection_fifos = shmat(identifiant, NULL, 0);      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((nom = nom_segment_mutexes(chemin, pid)) == NULL)      if (pid == getpid())
     {      {
         return(-1);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     }          {
               printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     if ((clef = ftok(nom, 1)) == -1)          (*s_etat_processus).var_volatile_alarme = -1;
           (*s_etat_processus).var_volatile_requete_arret = -1;
       }
       else
     {      {
         free(nom);          // Envoi d'un signal au thread maître du groupe.
         return(-1);  
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigurg);
           }
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   // Traitement de rpl_sigabort
   
   static inline void
   signal_abort(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     while((identifiant = shmget(clef,      verrouillage_gestionnaire_signaux(s_etat_processus);
             nombre_queues * sizeof(pthread_mutex_t),  
             S_IRUSR | S_IWUSR)) == -1);  
   
     projection_mutexes = shmat(identifiant, NULL, 0);      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
       {
           deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
       }
   
     if (pthread_mutex_lock(&(projection_mutexes[queue])) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         return(-1);          printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
                   (unsigned long long) pthread_self());
           fflush(stdout);
     }      }
   
     base = &(projection_fifos[(longueur_queue + 4) * queue]);      if (pid == getpid())
     buffer = &(base[4]);      {
           (*s_etat_processus).arret_depuis_abort = -1;
   
     // base[1] contient le prochain élément à écrire          /*
     buffer[base[1]++] = (int) pid;           * var_globale_traitement_retarde_stop :
     base[1] %= base[2];           *  0 -> traitement immédiat
            *  1 -> traitement retardé (aucun signal reçu)
            * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
            */
   
     // base[3] contient le nombre d'éléments non lus          if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
     if (base[3] <= 0)          {
     {              (*s_etat_processus).var_volatile_requete_arret = -1;
         pthread_mutex_unlock(&(projection_mutexes[queue]));          }
         shmdt(projection_mutexes);          else
         shmdt(projection_fifos);          {
         return(-1);              (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
           }
     }      }
       else
       {
           (*s_etat_processus).arret_depuis_abort = -1;
   
     base[3]--;          // Envoi d'un signal au thread maître du groupe.
   
     if (pthread_mutex_unlock(&(projection_mutexes[queue])) != 0)          if ((s_thread_principal = recherche_thread_principal(getpid()))
     {                  != NULL)
         shmdt(projection_mutexes);          {
         shmdt(projection_fifos);              envoi_signal_contexte(s_thread_principal, rpl_sigabort);
         return(-1);          }
     }      }
   
     // Fermeture des projections      deverrouillage_gestionnaire_signaux(s_etat_processus);
     shmdt(projection_mutexes);      return;
     shmdt(projection_fifos);  
     return(0);  
 }  }
   
 pid_t  
 origine_signal(int signal)  static inline void
   signal_hup(struct_processus *s_etat_processus, pid_t pid)
 {  {
     int             *base;      file                    *fichier;
     int             *buffer;  
     int             pid;  
     int             queue;  
   
     queue = queue_de_signal(signal);      unsigned char           nom[8 + 64 + 1];
   
     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",      verrouillage_gestionnaire_signaux(s_etat_processus);
             (int) getpid(), signal));  
   
     if (pthread_mutex_lock(&(mutexes[queue])) != 0)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         perror("lock");          deverrouillage_gestionnaire_signaux(s_etat_processus);
         return(-1);          return;
     }      }
   
     base = &(fifos[(longueur_queue + 4) * queue]);      snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
     buffer = &(base[4]);              (unsigned long long) getpid(),
     pid = buffer[base[0]++];              (unsigned long long) pthread_self());
     base[0] %= base[2];  
     base[3]++;  #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
     if (base[3] > base[2])      if ((fichier = fopen(nom, "w+")) != NULL)
     {      {
         uprintf("Base\n");          fclose(fichier);
         pthread_mutex_unlock(&(mutexes[queue]));  
         return(-1);          freopen(nom, "w", stdout);
           freopen(nom, "w", stderr);
     }      }
     if (pthread_mutex_unlock(&(mutexes[queue])) != 0)  
       freopen("/dev/null", "r", stdin);
   
   #   pragma GCC diagnostic pop
   
       if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         perror("unlock");          printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
         return(-1);                  (unsigned long long) pthread_self());
           fflush(stdout);
     }      }
   
     return((pid_t) pid);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
 }  }
   
 #endif  
   
 void  void
 interruption1(SIGHANDLER_ARGS)  traitement_exceptions_gsl(const char *reason, const char *file,
           int line, int gsl_errno)
 {  {
     pid_t                   pid;      code_erreur_gsl = gsl_errno;
       envoi_signal_processus(getpid(), rpl_sigexcept, d_faux);
     pthread_t               thread;      return;
   }
   
     struct_processus        *s_etat_processus;  static inline void
   signal_except(struct_processus *s_etat_processus, pid_t pid)
   {
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     volatile sig_atomic_t   exclusion = 0;      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
       {
           deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
       }
   
 #   ifdef _BROKEN_SIGINFO      (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
     pid = origine_signal(signal);      deverrouillage_gestionnaire_signaux(s_etat_processus);
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     verrouillage_gestionnaire_signaux();      return;
   }
   
   static inline void
   envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
           pid_t pid_source)
   {
     switch(signal)      switch(signal)
     {      {
         case SIGALRM :          case rpl_signull:
         {              break;
             if (pid == getpid())  
             {  
                 if ((s_etat_processus = recherche_thread(getpid(),  
                         pthread_self())) == NULL)  
                 {  
                     deverrouillage_gestionnaire_signaux();  
                      return;  
                 }  
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          case rpl_sigint:
                 {              signal_int(s_etat_processus, pid_source);
                     printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(),              break;
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())          case rpl_sigterm:
                 {              signal_term(s_etat_processus, pid_source);
                     kill((*s_etat_processus).pid_processus_pere, signal);              break;
                 }  
                 else          case rpl_sigstart:
                 {              signal_start(s_etat_processus, pid_source);
                     (*s_etat_processus).var_volatile_alarme = -1;              break;
                     (*s_etat_processus).var_volatile_requete_arret = -1;  
                 }          case rpl_sigcont:
               signal_cont(s_etat_processus, pid_source);
               break;
   
           case rpl_sigstop:
               signal_stop(s_etat_processus, pid_source);
               break;
   
           case rpl_sigabort:
               signal_abort(s_etat_processus, pid_source);
               break;
   
           case rpl_sigurg:
               signal_urg(s_etat_processus, pid_source);
               break;
   
           case rpl_siginject:
               signal_inject(s_etat_processus, pid_source);
               break;
   
           case rpl_sigalrm:
               signal_alrm(s_etat_processus, pid_source);
               break;
   
           case rpl_sighup:
               signal_hup(s_etat_processus, pid_source);
               break;
   
           case rpl_sigtstp:
               signal_tstp(s_etat_processus, pid_source);
               break;
   
           case rpl_sigexcept:
               signal_except(s_etat_processus, pid_source);
               break;
   
           default:
               if ((*s_etat_processus).langue == 'F')
               {
                   printf("+++System : Signal inconnu (%d) !\n", signal);
             }              }
             else              else
             {              {
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)                  printf("+++System : Spurious signal (%d) !\n", signal);
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }              }
   
             break;              break;
         }      }
   
       return;
   }
   
   void
   scrutation_interruptions(struct_processus *s_etat_processus)
   {
       // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
   
       // Les pointeurs de lecture pointent sur les prochains éléments
       // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
       // écrire.
   
         case SIGINT :      if (sem_trywait(semaphore_queue_signaux) == 0)
       {
           while((*s_queue_signaux).pointeur_lecture !=
                   (*s_queue_signaux).pointeur_ecriture)
         {          {
             /*              // Il y a un signal en attente dans le segment partagé. On le
              * Une vieille spécification POSIX permet au pointeur siginfo              // traite.
              * d'être nul dans le cas d'un ^C envoyé depuis le clavier.  
              * Solaris suit en particulier cette spécification.  
              */  
   
 #           ifndef _BROKEN_SIGINFO              if (pthread_mutex_lock(&mutex_liste_threads) != 0)
             if (siginfo == NULL)  
             {              {
                 kill(getpid(), signal);                  return;
               }
   
               envoi_interruptions(s_etat_processus,
                       (*s_queue_signaux).queue[(*s_queue_signaux)
                       .pointeur_lecture].signal, (*s_queue_signaux).queue
                       [(*s_queue_signaux).pointeur_lecture].pid);
               (*s_queue_signaux).pointeur_lecture =
                       ((*s_queue_signaux).pointeur_lecture + 1)
                       % LONGUEUR_QUEUE_SIGNAUX;
   
   #           ifndef IPCS_SYSV
               if (msync(s_queue_signaux, sizeof(s_queue_signaux),
                       MS_ASYNC | MS_INVALIDATE) != 0)
               {
                   sem_post(semaphore_queue_signaux);
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
             }              }
             else  
 #           endif  #           endif
             if (pid == getpid())  
               if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
               {
                   return;
               }
   
               while(sem_wait(semaphore_signalisation) != 0)
             {              {
                 if ((s_etat_processus = recherche_thread(getpid(),                  if (errno != EINTR)
                         pthread_self())) == NULL)  
                 {                  {
                     deverrouillage_gestionnaire_signaux();                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     return;                      return;
                 }                  }
               }
           }
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          sem_post(semaphore_queue_signaux);
                 {      }
                     printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())      // Interruptions qui arrivent depuis le groupe courant de threads.
                 {  
                     kill((*s_etat_processus).pid_processus_pere, signal);  
                 }  
                 else  
                 {  
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;  
   
                     while(exclusion == 1);      if (pthread_mutex_trylock(&mutex_liste_threads) == 0)
                     exclusion = 1;      {
           if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
           {
               while((*s_etat_processus).pointeur_signal_lecture !=
                       (*s_etat_processus).pointeur_signal_ecriture)
               {
                   // Il y a un signal dans la queue du thread courant.
                   // On le traite.
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)                  envoi_interruptions(s_etat_processus,
                           (*s_etat_processus).signaux_en_queue
                           [(*s_etat_processus).pointeur_signal_lecture],
                           getpid());
                   (*s_etat_processus).pointeur_signal_lecture =
                           ((*s_etat_processus).pointeur_signal_lecture + 1)
                           % LONGUEUR_QUEUE_SIGNAUX;
   
                   while(sem_wait(semaphore_signalisation) != 0)
                   {
                       if (errno != EINTR)
                     {                      {
                         deverrouillage_gestionnaire_signaux();                          if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
                         exclusion = 0;                          {
                               (*s_etat_processus).erreur_systeme = d_es_processus;
                               return;
                           }
   
                           (*s_etat_processus).erreur_systeme = d_es_processus;
                         return;                          return;
                     }                      }
                   }
               }
   
                     if (strncmp(getenv("LANG"), "fr", 2) == 0)              pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
                     {          }
                         printf("+++Interruption\n");  
                     }  
                     else  
                     {  
                         printf("+++Interrupt\n");  
                     }  
   
                     fflush(stdout);          pthread_mutex_unlock(&mutex_liste_threads);
       }
   
       return;
   }
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;  
                     (*s_etat_processus).var_volatile_alarme = -1;  
   
                     exclusion = 0;  /*
                 }  ================================================================================
     Fonction renvoyant le nom du segment de mémoire partagée en fonction
     du pid du processus.
   ================================================================================
     Entrée : Chemin absolue servant de racine, pid du processus
   --------------------------------------------------------------------------------
     Sortie : NULL ou nom du segment
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   static unsigned char *
   nom_segment(unsigned char *chemin, pid_t pid)
   {
       unsigned char               *fichier;
   
   #   ifdef IPCS_SYSV // !POSIX
   #       ifndef OS2 // !OS2
   
               if ((fichier = sys_malloc((strlen(chemin) + 1 + 256 + 1) *
                       sizeof(unsigned char))) == NULL)
               {
                   return(NULL);
             }              }
             else  
               sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
   #       else // OS2
               if ((fichier = sys_malloc((10 + 256 + 1) * sizeof(unsigned char)))
                       == NULL)
             {              {
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)                  return(NULL);
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }              }
   
             break;              sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
         }  #       endif // OS2
   #   else // POSIX
   
         default :          if ((fichier = sys_malloc((1 + 256 + 1) *
                   sizeof(unsigned char))) == NULL)
         {          {
             BUG(1, uprintf("[%d] Unknown signal %d in this context\n",              return(NULL);
                     (int) getpid(), signal));  
             break;  
         }          }
     }  
   
     deverrouillage_gestionnaire_signaux();          sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
     return;  #   endif
   
       return(fichier);
 }  }
   
 void  
 interruption2(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  /*
   ================================================================================
     Fonctions d'envoi d'un signal à un thread ou à un processus.
   ================================================================================
     Entrée : processus et signal
   --------------------------------------------------------------------------------
     Sortie : erreur
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
     struct_processus        *s_etat_processus;  int
   envoi_signal_processus(pid_t pid, enum signaux_rpl signal,
           logical1 test_ouverture)
   {
   #   ifndef OS2
           int                         segment;
   #   endif
   
 #   ifdef _BROKEN_SIGINFO  #   ifndef IPCS_SYSV
     pid = origine_signal(signal);          sem_t                       *semaphore;
 #   else          sem_t                       *signalisation;
     pid = (*siginfo).si_pid;  #   else
           sem_t                       *semaphore;
           sem_t                       *signalisation;
   #       ifndef OS2
               int                     desc;
               key_t                   clef;
   #       endif
 #   endif  #   endif
   
     verrouillage_gestionnaire_signaux();      struct_queue_signaux            *queue;
   
 #   ifndef _BROKEN_SIGINFO      struct timespec                 attente;
     if (siginfo == NULL)  
       unsigned char                   *nom;
   
       // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
       // mémoire puis d'y inscrire le signal à traiter.
   
       if (pid == getpid())
     {      {
         /*          // Le signal est envoyé au même processus.
          * Le signal SIGFSTP provient de la mort du processus de contrôle.  
          * Sous certains systèmes (Linux...), la mort du terminal de contrôle  
          * se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres  
          * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo  
          * non initialisée (pointeur NULL) issue de TERMIO.  
          */  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if (s_queue_signaux == NULL)
         {          {
             pthread_kill(thread, SIGHUP);              return(1);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }  
     else          while(sem_wait(semaphore_queue_signaux) != 0)
 #   endif  
     if (pid == getpid())  
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              if (errno != EINTR)
             return;              {
                   return(1);
               }
         }          }
   
         /*          (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
          *  0 => fonctionnement normal                  .pid = pid;
          * -1 => requête          (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
          *  1 => requête acceptée en attente de traitement                  .signal = signal;
          */  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          (*s_queue_signaux).pointeur_ecriture =
                   ((*s_queue_signaux).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
   #       ifndef IPCS_SYSV
           if (msync(s_queue_signaux, sizeof(s_queue_signaux),
                   MS_ASYNC | MS_INVALIDATE) != 0)
         {          {
             printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(),              sem_post(semaphore_queue_signaux);
                     (unsigned long long) pthread_self());              return(1);
             fflush(stdout);  
         }          }
   #       endif
   
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          if (sem_post(semaphore_queue_signaux) != 0)
         {          {
             kill((*s_etat_processus).pid_processus_pere, signal);              return(1);
         }          }
         else  
           if (sem_post(semaphore_signalisation) != 0)
         {          {
             (*s_etat_processus).var_volatile_requete_arret2 = -1;              return(1);
         }          }
     }      }
     else      else
     {      {
         // Envoi d'un signal au thread maître du groupe.          // Le signal est envoyé depuis un processus distinct.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  #       ifdef IPCS_SYSV
         {              if ((nom = nom_segment(racine_segment, pid)) == NULL)
             pthread_kill(thread, SIGTSTP);              {
             deverrouillage_gestionnaire_signaux();                  return(1);
             return;              }
         }  
     }  
   
     deverrouillage_gestionnaire_signaux();  #           ifndef OS2 // SysV
     return;                  if (test_ouverture == d_vrai)
 }                  {
                       attente.tv_sec = 0;
                       attente.tv_nsec = GRANULARITE_us * 1000;
   
 void                      while((desc = open(nom, O_RDWR)) == -1)
 interruption3(SIGHANDLER_ARGS)                      {
 {                          nanosleep(&attente, NULL);
     pid_t                   pid;                          INCR_GRANULARITE(attente.tv_nsec);
                       }
                   }
                   else
                   {
                       if ((desc = open(nom, O_RDWR)) == -1)
                       {
                           sys_free(nom);
                           return(1);
                       }
                   }
   
     struct_processus        *s_etat_processus;                  close(desc);
   
     static int              compteur = 0;                  if ((clef = ftok(nom, 1)) == -1)
                   {
                       sys_free(nom);
                       return(1);
                   }
   
 #   ifdef _BROKEN_SIGINFO                  sys_free(nom);
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     verrouillage_gestionnaire_signaux();                  if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
                           == -1)
                   {
                       return(1);
                   }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)                  queue = shmat(segment, NULL, 0);
     {  #           else // OS/2
         deverrouillage_gestionnaire_signaux();                  if (test_ouverture == d_vrai)
         return;                  {
     }                      attente.tv_sec = 0;
                       attente.tv_nsec = GRANULARITE_us * 1000;
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)                      while(DosGetNamedSharedMem((PVOID) &queue, nom,
     {                              PAG_WRITE | PAG_READ) != 0)
         printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(),                      {
                 (unsigned long long) pthread_self());                          nanosleep(&attente, NULL);
         fflush(stdout);                          INCR_GRANULARITE(attente.tv_nsec);
     }                      }
                   }
                   else
                   {
                       if (DosGetNamedSharedMem((PVOID) &queue, nom,
                               PAG_WRITE | PAG_READ) != 0)
                       {
                           sys_free(nom);
                           return(1);
                       }
                   }
   
     if ((*s_etat_processus).var_volatile_recursivite == -1)                  sys_free(nom);
     {  #           endif
         // Segfault dans un appel de fonction récursive  #       else // POSIX
         deverrouillage_gestionnaire_signaux();              if ((nom = nom_segment(racine_segment, pid)) == NULL)
         longjmp(contexte, -1);              {
     }                  return(1);
     else              }
     {  
         // Segfault dans une routine interne              if (test_ouverture == d_vrai)
         if (strncmp(getenv("LANG"), "fr", 2) == 0)              {
                   attente.tv_sec = 0;
                   attente.tv_nsec = GRANULARITE_us * 1000;
   
                   while((segment = shm_open(nom, O_RDWR, 0)) == -1)
                   {
                       nanosleep(&attente, NULL);
                       INCR_GRANULARITE(attente.tv_nsec);
                   }
               }
               else
               {
                   if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
                   {
                       sys_free(nom);
                       return(1);
                   }
               }
   
               sys_free(nom);
   
               if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
                       PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
                       MAP_FAILED)
               {
                   close(segment);
                   return(1);
               }
   #       endif
   
           // À ce moment, le segment de mémoire partagée est projeté
           // dans l'espace du processus.
   
           if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
         {          {
             printf("+++Système : Violation d'accès (dépassement de pile)\n");  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
               return(1);
         }          }
         else  
           if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
                   == SEM_FAILED)
         {          {
             printf("+++System : Access violation (stack overflow)\n");  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(semaphore);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(semaphore);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(semaphore);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(semaphore);
               return(1);
         }          }
   
         fflush(stdout);          while(sem_wait(semaphore) != 0)
           {
               if (errno != EINTR)
               {
   #               ifndef IPCS_SYSV // POSIX
                       if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE)
                               != 0)
                       {
                           munmap(queue, sizeof(struct_queue_signaux));
                           sem_close(semaphore);
                           sem_close(signalisation);
                           close(segment);
                           return(1);
                       }
   
                       if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           close(segment);
                           return(1);
                       }
   
                       close(segment);
   #               else // IPCS_SYSV
   #                   ifndef OS2 // SysV
                           if (shmdt(queue) != 0)
                           {
                               sem_close(semaphore);
                               sem_close(signalisation);
                               return(1);
                           }
   #                   else // OS/2
                           // Pendant de DosGetNamedSHaredMem()
   #                   endif
   #               endif
   
                   sem_close(semaphore);
                   sem_close(signalisation);
                   return(1);
               }
           }
   
         compteur++;          (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
           (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
   
         if (compteur > 1)          (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
           if (sem_post(semaphore) != 0)
         {          {
             deverrouillage_gestionnaire_signaux();  #           ifndef IPCS_SYSV // POSIX
             exit(EXIT_FAILURE);                  if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(semaphore);
               sem_close(signalisation);
               return(1);
         }          }
         else  
           if (sem_close(semaphore) != 0)
         {          {
             deverrouillage_gestionnaire_signaux();  #           ifndef IPCS_SYSV // POSIX
             longjmp(contexte_initial, -1);                  if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(signalisation);
               return(1);
         }          }
     }  
   
     deverrouillage_gestionnaire_signaux();          if (sem_post(signalisation) != 0)
     return;          {
 }  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
 void                  if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 interruption4(SIGHANDLER_ARGS)                  {
 {                      close(segment);
     pid_t                   pid;                      sem_close(signalisation);
                       return(1);
                   }
   
     struct_processus        *s_etat_processus;                  close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
 #   ifdef _BROKEN_SIGINFO              sem_close(signalisation);
     pid = origine_signal(signal);              return(1);
 #   else          }
     pid = (*siginfo).si_pid;  
 #   endif  
   
     verrouillage_gestionnaire_signaux();          if (sem_close(signalisation) != 0)
           {
   #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       return(1);
                   }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)                  if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
     {                  {
         deverrouillage_gestionnaire_signaux();                      close(segment);
         return;                      return(1);
     }                  }
   
     /*                  close(segment);
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)  #           else // IPCS_SYSV
      */  #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              return(1);
     {          }
         printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  #       ifndef IPCS_SYSV // POSIX
         fflush(stdout);              if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
               {
                   munmap(queue, sizeof(struct_queue_signaux));
                   close(segment);
                   return(1);
               }
   
               if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
               {
                   close(segment);
                   return(1);
               }
   
               close(segment);
   #       else // IPCS_SYSV
   #           ifndef OS2 // SysV
                   if (shmdt(queue) != 0)
                   {
                       return(1);
                   }
   #           else // OS/2
                   // Pendant de DosGetNamedSHaredMem()
   #           endif
   #       endif
     }      }
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  int
 interruption5(SIGHANDLER_ARGS)  envoi_signal_thread(struct_processus *s_contexte,
           pthread_t tid, enum signaux_rpl signal)
 {  {
     pid_t                   pid;      // Un signal est envoyé d'un thread à un autre thread du même processus.
   
     pthread_t               thread;      int                                     ios;
   
     struct_processus        *s_etat_processus;      struct timespec                         attente;
   
 #   ifdef _BROKEN_SIGINFO      volatile struct_liste_chainee_volatile  *l_element_courant;
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     verrouillage_gestionnaire_signaux();      struct_processus                        *s_etat_processus;
   
     if (pid == getpid())      if (s_contexte != NULL)
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          attente.tv_sec = 0;
                 == NULL)          attente.tv_nsec = GRANULARITE_us * 1000;
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          while((ios = pthread_mutex_trylock(&mutex_liste_threads)) != 0)
         {          {
             printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),              if (ios != EBUSY)
                     (unsigned long long) pthread_self());              {
             fflush(stdout);                  return(1);
         }              }
   
         /*              if (sem_post(&((*s_contexte).semaphore_fork)) != 0)
          * var_globale_traitement_retarde_stop :              {
          *  0 -> traitement immédiat                  return(1);
          *  1 -> traitement retardé (aucun signal reçu)              }
          * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)  
          */  
   
         if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)              nanosleep(&attente, NULL);
         {              INCR_GRANULARITE(attente.tv_nsec);
             (*s_etat_processus).var_volatile_requete_arret = -1;  
         }              while(sem_wait(&((*s_contexte).semaphore_fork)) != 0)
         else              {
         {                  if (errno != EINTR)
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;                  {
                       return(1);
                   }
               }
         }          }
     }      }
     else      else
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          if (pthread_mutex_lock(&mutex_liste_threads) != 0)
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              return(1);
             return;  
         }          }
       }
   
         // Envoi d'un signal au thread maître du groupe.      l_element_courant = liste_threads;
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)      while(l_element_courant != NULL)
       {
           if (((*((struct_thread *) (*l_element_courant).donnee)).pid
                   == getpid()) && (pthread_equal((*((struct_thread *)
                   (*l_element_courant).donnee)).tid, tid) != 0))
         {          {
             pthread_kill(thread, signal);              break;
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
   
           l_element_courant = (*l_element_courant).suivant;
     }      }
   
     deverrouillage_gestionnaire_signaux();      if (l_element_courant == NULL)
     return;      {
 }          pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
 void      s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
 interruption6(SIGHANDLER_ARGS)              .s_etat_processus;
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;      if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
       {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
 #   ifdef _BROKEN_SIGINFO      (*s_etat_processus).signaux_en_queue
     pid = origine_signal(signal);              [(*s_etat_processus).pointeur_signal_ecriture] = signal;
 #   else      (*s_etat_processus).pointeur_signal_ecriture =
     pid = (*siginfo).si_pid;              ((*s_etat_processus).pointeur_signal_ecriture + 1)
 #   endif              % LONGUEUR_QUEUE_SIGNAUX;
   
     verrouillage_gestionnaire_signaux();      if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
       {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     {      {
         deverrouillage_gestionnaire_signaux();          return(1);
         return;  
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (sem_post(semaphore_signalisation) != 0)
     {      {
         printf("[%d] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(),          return(1);
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  int
 interruption7(SIGHANDLER_ARGS)  envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
           enum signaux_rpl signal)
 {  {
     pid_t                   pid;      pthread_mutex_lock(&((*s_etat_processus_a_signaler).mutex_signaux));
       (*s_etat_processus_a_signaler).signaux_en_queue
     struct_processus        *s_etat_processus;              [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =
               signal;
 #   ifdef _BROKEN_SIGINFO      (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
     pid = origine_signal(signal);              ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
 #   else              % LONGUEUR_QUEUE_SIGNAUX;
     pid = (*siginfo).si_pid;      pthread_kill((*s_etat_processus_a_signaler).tid, SIGUSR2);
 #   endif      pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
   
     verrouillage_gestionnaire_signaux();  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if (sem_post(semaphore_signalisation) != 0)
     {      {
         deverrouillage_gestionnaire_signaux();          return(1);
         return;  
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      return(0);
     {  }
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }  
   
     (*s_etat_processus).var_volatile_requete_arret = -1;  
     deverrouillage_gestionnaire_signaux();  
   
     BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));  /*
     return;  ================================================================================
 }    Fonction créant un segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
 void  void
 interruption8(SIGHANDLER_ARGS)  creation_queue_signaux(struct_processus *s_etat_processus)
 {  {
     pid_t                   pid;      pthread_attr_t                  attributs;
   
     pthread_t               thread;      unsigned char                   *nom;
   
     struct_processus        *s_etat_processus;      racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
   
 #   ifdef _BROKEN_SIGINFO  #   ifndef IPCS_SYSV // POSIX
     pid = origine_signal(signal);          if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
 #   else                  getpid())) == NULL)
     pid = (*siginfo).si_pid;          {
 #   endif              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     verrouillage_gestionnaire_signaux();          if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
                   S_IRUSR | S_IWUSR)) == -1)
           {
               if (errno != EEXIST)
               {
                   sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     if (pid == getpid())              if ((*s_etat_processus).langue == 'F')
     {              {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))                  printf("+++Attention : Le segment de mémoire %s préexiste !\n",
                 == NULL)                          nom);
               }
               else
               {
                   printf("+++Warning: %s memory segment preexists!\n", nom);
               }
   
               if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_TRUNC,
                       S_IRUSR | S_IWUSR)) == -1)
               {
                   sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
           }
   
           if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
         {          {
             deverrouillage_gestionnaire_signaux();              sys_free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
                   PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
   
           if (((void *) s_queue_signaux) == ((void *) -1))
         {          {
             printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),              if (shm_unlink(nom) == -1)
                     (unsigned long long) pthread_self());              {
             fflush(stdout);                  sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               sys_free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
   
         (*s_etat_processus).var_volatile_alarme = -1;          sys_free(nom);
         (*s_etat_processus).var_volatile_requete_arret = -1;  
     }  
     else  
     {  
         // Envoi d'un signal au thread maître du groupe.  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
                   == SEM_FAILED)
         {          {
             pthread_kill(thread, SIGURG);              (*s_etat_processus).erreur_systeme = d_es_processus;
             deverrouillage_gestionnaire_signaux();  
             return;              return;
         }          }
     }  
   
     deverrouillage_gestionnaire_signaux();          if ((semaphore_signalisation = sem_init2(0, getpid(),
     return;                  SEM_SIGNALISATION)) == SEM_FAILED)
 }          {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
 void          if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
 interruption9(SIGHANDLER_ARGS)                  SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
 {          {
     pid_t                   pid;              (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
     struct_processus        *s_etat_processus;          (*s_queue_signaux).pointeur_lecture = 0;
           (*s_queue_signaux).pointeur_ecriture = 0;
   
 #   ifdef _BROKEN_SIGINFO          (*s_queue_signaux).requete_arret = d_faux;
     pid = origine_signal(signal);  
 #   else          if (msync(s_queue_signaux, sizeof(struct_queue_signaux),
     pid = (*siginfo).si_pid;                  MS_ASYNC | MS_INVALIDATE) != 0)
 #   endif          {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   #   else // IPCS_SYSV
   #       ifndef OS2
               int                             segment;
               int                             support;
   
     verrouillage_gestionnaire_signaux();              key_t                           clef;
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)              // Création d'un segment de données associé au PID du processus
     {              // courant
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              if ((nom = nom_segment((*s_etat_processus)
     {                      .chemin_fichiers_temporaires, getpid())) == NULL)
         printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),              {
                 (unsigned long long) pthread_self());                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         fflush(stdout);                  return;
     }              }
   
     deverrouillage_gestionnaire_signaux();              if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
                       S_IRUSR | S_IWUSR)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
                   return;
               }
   
 #   ifdef _BROKEN_SIGINFO              if ((clef = ftok(nom, 1)) == -1)
     if (queue_in(getpid(), signal) != 0)              {
     {                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;                  return;
     }              }
   
     interruption11(signal);              close(support);
 #   else              sys_free(nom);
     interruption11(signal, siginfo, context);  
 #   endif  
     return;  
 }  
   
 void              if ((segment = shmget(clef, sizeof(struct_queue_signaux),
 interruption10(SIGHANDLER_ARGS)                      IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
 {              {
     file                    *fichier;                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     pid_t                   pid;              s_queue_signaux = shmat(segment, NULL, 0);
               f_queue_signaux = segment;
   
     struct_processus        *s_etat_processus;              if (((void *) s_queue_signaux) == ((void *) -1))
               {
                   if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return;
                   }
   
     unsigned char           nom[8 + 64 + 1];                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
 #   ifdef _BROKEN_SIGINFO              if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
     pid = origine_signal(signal);                      == SEM_FAILED)
 #   else              {
     pid = (*siginfo).si_pid;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               if ((semaphore_signalisation = sem_init2(0, getpid(),
                       SEM_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
                       SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       else // OS/2
               if ((nom = nom_segment(NULL, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
                       sizeof(struct_queue_signaux),
                       PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
               {
                   sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               sys_free(nom);
   
               if (sem_init(&((*s_queue_signaux).semaphore), 1, 1) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (sem_init(&((*s_queue_signaux).signalisation), 1, 0) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       endif
 #   endif  #   endif
   
     verrouillage_gestionnaire_signaux();      (*s_queue_signaux).controle = getpid();
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if (lancement_thread_signaux(s_etat_processus) == d_erreur)
     {      {
         deverrouillage_gestionnaire_signaux();          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),      // Lancement du thread de récupération des signaux.
             (unsigned long) pthread_self());  
   
     if ((fichier = fopen(nom, "w+")) != NULL)      if (pthread_attr_init(&attributs) != 0)
     {      {
         fclose(fichier);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
         freopen(nom, "w", stdout);      if (pthread_attr_setdetachstate(&attributs,
         freopen(nom, "w", stderr);              PTHREAD_CREATE_JOINABLE) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
     }      }
   
     freopen("/dev/null", "r", stdin);      if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
               thread_surveillance_signaux, s_etat_processus) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (pthread_attr_destroy(&attributs) != 0)
     {      {
         printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),          (*s_etat_processus).erreur_systeme = d_es_processus;
                 (unsigned long long) pthread_self());          return;
         fflush(stdout);  
     }      }
   
     deverrouillage_gestionnaire_signaux();  #   ifndef IPCS_SYSV
       if (msync(s_queue_signaux, sizeof(s_queue_signaux),
               MS_ASYNC | MS_INVALIDATE) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   #   endif
   
     return;      return;
 }  }
   
   
   /*
   ================================================================================
     Fonction libérant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
 void  void
 interruption11(SIGHANDLER_ARGS)  liberation_queue_signaux(struct_processus *s_etat_processus)
 {  {
     pid_t                   pid;  #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
               if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       else // OS/2
   #       endif
   #   else // POSIX
           sem_close(semaphore_queue_signaux);
           sem_close(semaphore_signalisation);
           sem_close(semaphore_arret_signalisation);
   
     pthread_t               thread;          if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     struct_processus        *s_etat_processus;          close(f_queue_signaux);
   #   endif
   
 #   ifdef _BROKEN_SIGINFO      return;
     pid = origine_signal(signal);  }
 #   else  
     pid = (*siginfo).si_pid;  
   /*
   ================================================================================
     Fonction détruisant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   void
   destruction_queue_signaux(struct_processus *s_etat_processus)
   {
   #   ifndef OS2
           unsigned char       *nom;
 #   endif  #   endif
   
     verrouillage_gestionnaire_signaux();      // On dépile les interruptions pour arrêter les SIGUSR2 sur
       // le processus courant.
   
     if (pid == getpid())      scrutation_interruptions(s_etat_processus);
   
       while(sem_wait(semaphore_arret_signalisation) != 0)
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          if (errno != EINTR)
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
       }
   
         (*s_etat_processus).arret_depuis_abort = -1;      (*s_queue_signaux).requete_arret = d_vrai;
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  #   ifndef IPCS_SYSV
         {      msync(s_queue_signaux, sizeof(s_queue_signaux), MS_ASYNC | MS_INVALIDATE);
             printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(),  #   endif
                     (unsigned long long) pthread_self());  
             fflush(stdout);  
         }  
   
         /*      sem_post(semaphore_arret_signalisation);
          * var_globale_traitement_retarde_stop :  
          *  0 -> traitement immédiat  
          *  1 -> traitement retardé (aucun signal reçu)  
          * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)  
          */  
   
         if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)      // Incrémenter le sémaphore pour être sûr de le débloquer.
         {  
             (*s_etat_processus).var_volatile_requete_arret = -1;      sem_post(semaphore_signalisation);
         }  
         else      if ((*s_queue_signaux).controle == getpid())
         {      {
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;          pthread_join((*s_queue_signaux).thread_signaux, NULL);
         }  
     }      }
     else      else
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          (*s_etat_processus).erreur_systeme = d_es_processus;
                 == NULL)          return;
         {      }
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         (*s_etat_processus).arret_depuis_abort = -1;      arret_thread_signaux(s_etat_processus);
   
         // Envoi d'un signal au thread maître du groupe.  #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
               // Il faut commencer par éliminer le sémaphore.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)              if (semctl((*semaphore_queue_signaux).sem, 0, IPC_RMID) == -1)
         {              {
             pthread_kill(thread, signal);                  (*s_etat_processus).erreur_systeme = d_es_processus;
             deverrouillage_gestionnaire_signaux();                  return;
             return;              }
         }  
     }  
   
     deverrouillage_gestionnaire_signaux();              unlink((*semaphore_queue_signaux).path);
     return;              sys_free((*semaphore_queue_signaux).path);
 }  
   
 void              if (semctl((*semaphore_signalisation).sem, 0, IPC_RMID) == -1)
 traitement_exceptions_gsl(const char *reason, const char *file,              {
         int line, int gsl_errno)                  (*s_etat_processus).erreur_systeme = d_es_processus;
 {                  return;
     struct_processus        *s_etat_processus;              }
   
     verrouillage_gestionnaire_signaux();              unlink((*semaphore_signalisation).path);
               sys_free((*semaphore_signalisation).path);
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)              if (semctl((*semaphore_arret_signalisation).sem, 0, IPC_RMID) == -1)
     {              {
         deverrouillage_gestionnaire_signaux();                  (*s_etat_processus).erreur_systeme = d_es_processus;
         return;                  return;
     }              }
   
     (*s_etat_processus).var_volatile_exception_gsl = gsl_errno;              unlink((*semaphore_arret_signalisation).path);
     deverrouillage_gestionnaire_signaux();              sys_free((*semaphore_arret_signalisation).path);
     return;  
 }  
   
 #ifdef _BROKEN_SIGINFO              if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
 #undef kill              if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
 #undef pthread_kill              {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
 int              if ((nom = nom_segment((*s_etat_processus)
 rpl_kill(pid_t pid, int signal)                      .chemin_fichiers_temporaires, getpid())) == NULL)
 {              {
     /*                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
      * Lorsqu'on veut interrompre le processus pid, on ouvre le segment                  return;
      * correspondant au processus en question et ou ajoute le pid dans la              }
      * queue.  
      */  
   
     if (signal != 0)              unlink(nom);
     {              sys_free(nom);
         if (queue_in(pid, signal) != 0)  #       else
               sem_close(&((*s_queue_signaux).semaphore));
               sem_destroy(&((*s_queue_signaux).semaphore));
   
               sem_close(&((*s_queue_signaux).signalisation));
               sem_destroy(&((*s_queue_signaux).signalisation));
   
               sem_close(&((*s_queue_signaux).arret_signalisation));
               sem_destroy(&((*s_queue_signaux).arret_signalisation));
   
               if (DosFreeMem(s_queue_signaux) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       endif
   #   else // POSIX
           sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
           sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
           sem_destroy2(semaphore_arret_signalisation, getpid(),
                   SEM_ARRET_SIGNALISATION);
   
           if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
         {          {
             return(-1);              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
     }  
   
     return(kill(pid, signal));          if ((nom = nom_segment(NULL, getpid())) == NULL)
 }          {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
 int          close(f_queue_signaux);
 rpl_pthread_kill(pthread_t tid, int signal)  
 {          if (shm_unlink(nom) != 0)
     if (signal != 0)  
     {  
         if (queue_in(getpid(), signal) != 0)  
         {          {
             return(-1);              sys_free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
     }  
   
     return(pthread_kill(tid, signal));          sys_free(nom);
 }  #   endif
   
 #endif      return;
   }
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.30  
changed lines
  Added in v.1.209


CVSweb interface <joel.bertrand@systella.fr>