Diff for /rpl/src/interruptions.c between versions 1.35 and 1.140

version 1.35, 2010/08/25 09:06:49 version 1.140, 2014/03/15 11:04:21
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.18    RPL/2 (R) version 4.1.17
   Copyright (C) 1989-2010 Dr. BERTRAND Joël    Copyright (C) 1989-2014 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 SIGALRM. 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 (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
           if (sem_wait(&(*s_queue_signaux).signalisation) == 0)
   #       else
           if (sem_wait(semaphore_signalisation) == 0)
   #       endif
           {
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               if (sem_wait(&(*s_queue_signaux).arret_signalisation) != 0)
   #           else
               if (sem_wait(semaphore_arret_signalisation) != 0)
   #           endif
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
               }
   
               if ((*s_queue_signaux).requete_arret == d_vrai)
               {
   #               if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
                   sem_post(&(*s_queue_signaux).arret_signalisation);
                   sem_post(&(*s_queue_signaux).signalisation);
   #               else
                   sem_post(semaphore_arret_signalisation);
                   sem_post(semaphore_signalisation);
   #               endif
   
                   break;
               }
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_post(&(*s_queue_signaux).arret_signalisation);
               sem_post(&(*s_queue_signaux).signalisation);
   #           else
               sem_post(semaphore_arret_signalisation);
               sem_post(semaphore_signalisation);
   #           endif
   
               nombre_signaux_envoyes = 0;
               sched_yield();
   
               // 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.
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_wait(&(*s_queue_signaux).semaphore);
   #           else
               sem_wait(semaphore_queue_signaux);
   #           endif
   
               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(), SIGALRM);
               }
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_post(&(*s_queue_signaux).semaphore);
   #           else
               sem_post(semaphore_queue_signaux);
   #           endif
   
               // 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, SIGALRM);
                       }
   
                       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 233  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;  
     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;
     }      }
   
     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 255  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      if (pthread_mutex_lock(&mutex_liste_threads) != 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;  
         }  
     }      }
   
     (*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 277  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) != 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) != 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;  
     sigset_t                                set;  
   
     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) != 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 256  retrait_thread(struct_processus *s_etat_ Line 340  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 354  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;  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
           while(sem_wait(&((*s_queue_signaux).signalisation)) != 0)
   #       else
           while(sem_wait(semaphore_signalisation) != 0)
   #       endif
           {
               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 397  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) != 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 422  retrait_thread_surveillance(struct_proce
   
     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 378  retrait_thread_surveillance(struct_proce Line 436  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);
         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 452  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);
             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);
             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) != 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;
 }  }
   
Line 460  verrouillage_threads_concurrents(struct_ Line 490  verrouillage_threads_concurrents(struct_
 {  {
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_lock(&mutex_liste_threads) != 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;
             (*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 505  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)                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 {                  return;
                     (*s_etat_processus).erreur_systeme = d_es_processus;  
                     return;  
                 }  
             }              }
         }          }
   
Line 517  deverrouillage_threads_concurrents(struc Line 537  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 560  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 574  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 593  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 627  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 675  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 695  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 723  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 796  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             for(i = 0; i < (*s_etat_processus).nombre_variables; i++)              // ne peut être effacé qu'une seule fois
             {  
                 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  
             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));
                 {  
                     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;
                 }                  }
               }
   
               liberation_arbre_variables(s_etat_processus,
                       (*s_etat_processus).s_arbre_variables, d_faux);
   
                 pthread_mutex_trylock(&((*(*s_etat_processus)              l_element_statique_courant = (*s_etat_processus)
                         .s_liste_variables_partagees).mutex));                      .l_liste_variables_statiques;
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_partagees).mutex));              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 1287  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
   
               liberation_contexte_cas(s_etat_processus);
             free(s_etat_processus);              free(s_etat_processus);
   
             s_etat_processus = candidat;              s_etat_processus = candidat;
Line 1350  liberation_threads(struct_processus *s_e Line 1317  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);
             return;              return;
         }          }
   
Line 1369  liberation_threads(struct_processus *s_e Line 1337  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);
                 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 1364  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);
                 return;                  return;
             }              }
         }          }
Line 1409  liberation_threads(struct_processus *s_e Line 1380  liberation_threads(struct_processus *s_e
   
     liste_threads_surveillance = NULL;      liste_threads_surveillance = NULL;
   
 #   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);  
         (*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 1396  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 1421  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 1461  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 1486  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;  
   
     sigset_t    oldset;  
     sigset_t    set;  
   
     sem_t       *sem;  
   
     if ((sem = pthread_getspecific(semaphore_fork_processus_courant))  
             != NULL)  
     {  
         if (sem_post(sem) != 0)  
         {  
             BUG(1, uprintf("Lock error !\n"));  
             return;  
         }  
     }  
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !  
   
     sigfillset(&set);  
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)      if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
 #   else  #   else
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)      if (sem_post((*s_etat_processus).semaphore_fork) != 0)
 #   endif  #   endif
     {      {
         if (errno != EINTR)          BUG(1, uprintf("Lock error !\n"));
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
Line 1556  verrouillage_gestionnaire_signaux() Line 1504  verrouillage_gestionnaire_signaux()
     if (sem_post(semaphore_gestionnaires_signaux) == -1)      if (sem_post(semaphore_gestionnaires_signaux) == -1)
 #   endif  #   endif
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  #       ifndef SEMAPHORES_NOMMES
           sem_wait(&((*s_etat_processus).semaphore_fork));
   #       else
           sem_wait((*s_etat_processus).semaphore_fork);
   #       endif
         BUG(1, uprintf("Lock error !\n"));          BUG(1, uprintf("Lock error !\n"));
         return;          return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      return;
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)  }
 #   else  
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   endif  
     {  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         BUG(1, uprintf("Lock error !\n"));  
         return;  
     }  
   
   static inline void
   deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
   {
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
     if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0)      while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
 #   else  #   else
     if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0)      while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
 #   endif  #   endif
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);          if (errno != EINTR)
         BUG(1, uprintf("Unlock error !\n"));  
         return;  
     }  
   
     if (semaphore == 1)  
     {  
         // Le semaphore ne peut être pris par le thread qui a appelé  
         // le gestionnaire de signal car le signal est bloqué par ce thread  
         // 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  
         while(sem_trywait(&semaphore_liste_threads) == -1)  
 #       else  
         while(sem_trywait(semaphore_liste_threads) == -1)  
 #       endif  
         {          {
             if ((errno != EINTR) && (errno != EAGAIN))              BUG(1, uprintf("Unlock error !\n"));
             {              return;
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
   
                 while(sem_wait(sem) == -1)  
                 {  
                     if (errno != EINTR)  
                     {  
                         BUG(1, uprintf("Lock error !\n"));  
                         return;  
                     }  
                 }  
   
                 BUG(1, uprintf("Lock error !\n"));  
                 return;  
             }  
   
             sched_yield();  
         }          }
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
   
     return;      return;
 }  }
   
 static inline void  /*
 deverrouillage_gestionnaire_signaux()  ================================================================================
 {    Fonctions de gestion des signaux dans les threads.
     int         semaphore;  
   
     sem_t       *sem;    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é.
   ================================================================================
   */
   
     sigset_t    oldset;  #define test_signal(signal) \
     sigset_t    set;      if (signal_test == SIGTEST) { signal_test = signal; return; }
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !  static int          pipe_signaux;
   
     sigfillset(&set);  logical1
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  lancement_thread_signaux(struct_processus *s_etat_processus)
   {
       pthread_attr_t                  attributs;
   
 #   ifndef SEMAPHORES_NOMMES      void                            *argument;
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)  
 #   else  
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)  
 #   endif  
     {  
         if (errno != EINTR)  
         {  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }  
     }  
   
 #   ifndef SEMAPHORES_NOMMES      if (pipe((*s_etat_processus).pipe_signaux) != 0)
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   else  
     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("Unlock error !\n"));          return(d_erreur);
         return;  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      pipe_signaux = (*s_etat_processus).pipe_signaux[1];
     while(sem_wait(&semaphore_gestionnaires_signaux) == -1)  
 #   else      if (pthread_attr_init(&attributs) != 0)
     while(sem_wait(semaphore_gestionnaires_signaux) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return(d_erreur);
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             BUG(1, uprintf("Unlock error !\n"));  
             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 ((sem = pthread_getspecific(semaphore_fork_processus_courant))      argument = (*s_etat_processus).pipe_signaux;
             != NULL)  
       if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
               thread_signaux, argument) != 0)
     {      {
         while(sem_wait(sem) == -1)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return(d_erreur);
             if (errno != EINTR)  
             {  
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
                 BUG(1, uprintf("Unlock error !\n"));  
                 return;  
             }  
         }  
     }      }
   
     if (semaphore == 1)      return(d_absence_erreur);
     {  }
 #       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);  
   
             BUG(1, uprintf("Unlock error !\n"));  logical1
             return;  arret_thread_signaux(struct_processus *s_etat_processus)
         }  {
     }      unsigned char       signal;
       ssize_t             n;
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);      signal = (unsigned char ) (rpl_sigmax & 0xFF);
     sigpending(&set);  
   
     return;      do
 }      {
           n = write((*s_etat_processus).pipe_signaux[1], &signal, sizeof(signal));
   
 #ifdef _BROKEN_SIGINFO          if (n < 0)
           {
               return(d_erreur);
           }
       } while(n != 1);
   
 #define longueur_queue  256      pthread_join((*s_etat_processus).thread_signaux, NULL);
 #define nombre_queues   13  
   
 static int              *fifos;      close((*s_etat_processus).pipe_signaux[0]);
 static int              markov;      close((*s_etat_processus).pipe_signaux[1]);
 static int              segment;  
 static sem_t            *semaphores[nombre_queues];  
 static sem_t            *semaphore_global;  
   
 #ifdef IPCS_SYSV      return(d_absence_erreur);
 static unsigned char    *chemin = NULL;  }
 #endif  
   
 unsigned char *  void *
 nom_segment(unsigned char *chemin, pid_t pid)  thread_signaux(void *argument)
 {  {
     unsigned char               *fichier;      int                     *pipe;
   
 #   ifdef IPCS_SYSV      sigset_t                masque;
     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);      struct pollfd           fds;
 #   else  
     if ((fichier = malloc((1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);      unsigned char           signal;
 #   endif  
   
     return(fichier);      pipe = (int *) argument;
 }      fds.fd = pipe[0];
       fds.events = POLLIN;
       fds.revents = 0;
   
 unsigned char *      sigfillset(&masque);
 nom_semaphore(pid_t pid, int queue)      pthread_sigmask(SIG_BLOCK, &masque, NULL);
 {  
     unsigned char               *fichier;  
   
     if ((fichier = malloc((256 + 1) * sizeof(unsigned char))) == NULL)      do
     {      {
         return(NULL);          if (poll(&fds, 1, -1) == -1)
     }          {
               pthread_exit(NULL);
           }
   
     sprintf(fichier, "/RPL-SIGESMAPHORES-%d-%d", (int) pid, queue);          read(fds.fd, &signal, 1);
   
     return(fichier);          if (signal != (0xFF & rpl_sigmax))
           {
               envoi_signal_processus(getpid(), signal);
               // Un signal SIGALRM est envoyé par le thread de surveillance
               // des signaux jusqu'à ce que les signaux soient tous traités.
           }
       } while(signal != (0xFF & rpl_sigmax));
   
       pthread_exit(NULL);
 }  }
   
 inline int  // Récupération des signaux
 queue_de_signal(int signal)  // - SIGINT  (arrêt au clavier)
   // - SIGTERM (signal d'arrêt en provenance du système)
   
   void
   interruption1(int signal)
 {  {
       unsigned char       signal_tronque;
   
       test_signal(signal);
   
     switch(signal)      switch(signal)
     {      {
         case SIGINT:          case SIGINT:
             return(0);              signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
         case SIGTSTP:              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             return(1);              break;
         case SIGCONT:  
             return(2);          case SIGTERM:
         case SIGURG:              signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
             return(3);              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
         case SIGPIPE:              break;
             return(4);  
         case SIGALRM:          case SIGUSR1:
             return(5);              signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
         case SIGFSTOP:              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             return(6);              break;
         case SIGSTART:  
             return(7);          default:
         case SIGINJECT:              // SIGALRM
             return(8);              break;
         case SIGABORT:  
             return(9);  
         case SIGFABORT:  
             return(10);  
         case SIGSEGV:  
             return(11);  
         case SIGBUS:  
             return(12);  
     }      }
   
     return(-1);      return;
 }  }
   
   // Récupération des signaux
   // - 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  void
 creation_fifos_signaux(struct_processus *s_etat_processus)  interruption2(int signal)
 {  {
     /*      unsigned char       signal_tronque;
      * Signaux utilisés  
      * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP,  
      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT  
      */  
   
     int                             i;      test_signal(signal);
   
     unsigned char                   *nom;      signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
       write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
       return;
   }
   
 #   ifndef IPCS_SYSV // POSIX  void
   interruption3(int 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";
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,      test_signal(signal);
             getpid())) == NULL)  
       if (pid_processus_pere == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          kill(pid_processus_pere, SIGUSR1);
         return;  
     }      }
   
     if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,      if (signal != SIGUSR2)
             S_IRUSR | S_IWUSR)) == -1)  
     {      {
         free(nom);          write(STDERR_FILENO, message_1, strlen(message_1));
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }      }
       else
     if (ftruncate(segment, nombre_queues * ((2 * longueur_queue) + 4) *  
             sizeof(int)) == -1)  
     {      {
         free(nom);          write(STDERR_FILENO, message_2, strlen(message_2));
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }      }
   
     fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),      _exit(EXIT_FAILURE);
             PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0);  }
     close(segment);  
   
     if (((void *) fifos) == ((void *) -1))  
     {  
         if (shm_unlink(nom) == -1)  
         {  
             free(nom);  
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
             return;  
         }  
   
         free(nom);  // Récupération des signaux
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  // - SIGHUP
         return;  
     }  
   
     free(nom);  void
   interruption4(int signal)
   {
       unsigned char       signal_tronque;
   
 #   else // SystemV      test_signal(signal);
   
     file                            *desc;      signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
       write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
       return;
   }
   
     key_t                           clef;  // Récupération des signaux
   // - SIGPIPE
   
     // Création d'un segment de données associé au PID du processus courant  void
   interruption5(int signal)
   {
       unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
       unsigned char       signal_tronque;
   
     chemin = (*s_etat_processus).chemin_fichiers_temporaires;      test_signal(signal);
   
     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));
     }      }
   
     if ((desc = fopen(nom, "w")) == NULL)      write(STDERR_FILENO, message, strlen(message));
     {      return;
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;  }
         return;  
     }  
   
     fclose(desc);  inline static void
   signal_alrm(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       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 * ((2 * 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);
           }
           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;
   }
   
   inline static void
   signal_term(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 (((void *) fifos) == ((void *) -1))      if (pid == getpid())
     {      {
         if (shmctl(segment, IPC_RMID, 0) == -1)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
             return;                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if ((*s_etat_processus).pid_processus_pere != getpid())
         return;          {
     }              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigterm);
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
 #   endif              pthread_mutex_lock(&exclusion);
   
     /*              if ((*s_etat_processus).var_volatile_requete_arret == -1)
      * Structure d'une queue              {
      * 0 : pointeur en lecture sur le premier emplacement libre (int)                  deverrouillage_gestionnaire_signaux(s_etat_processus);
      * 1 : pointeur en écriture sur le premier emplacement à lire (int)                  pthread_mutex_unlock(&exclusion);
      * 2 : longueur de la queue (int)                  return;
      * 3 : éléments restants (int)              }
      * 4 à 4 + (2) : queue (int)  
      * 4 + (2) + 1 ) 4 + 2 * (2) : horodatage en centième de secondes.  
      */  
   
     for(i = 0; i < nombre_queues; i++)  
     {  
         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;  
     }  
   
     // Création des sémaphores : un sémaphore par signal et par queue              (*s_etat_processus).var_volatile_requete_arret = -1;
     // plus un sémaphore global pour tous les threads.              (*s_etat_processus).var_volatile_alarme = -1;
   
     for(i = 0; i < nombre_queues; i++)              pthread_mutex_unlock(&exclusion);
           }
       }
       else
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              envoi_signal_contexte(s_thread_principal, rpl_sigterm);
             return;  
         }          }
       }
   
       deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
         // Le sémaphore est créé en écrasant si nécessaire un sémaphore  inline static void
         // préexistant. Comme le nom du sémaphore contient l'identifiant du  signal_int(struct_processus *s_etat_processus, pid_t pid)
         // processus, il est anormal d'avoir un sémaphore de même nom  {
         // préexistant.      struct_processus        *s_thread_principal;
       volatile sig_atomic_t   exclusion = 0;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
       {
           if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
         if ((semaphores[i] = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,          if ((*s_etat_processus).pid_processus_pere != getpid())
                 1)) == SEM_FAILED)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
             return;                      rpl_sigint);
         }          }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
         free(nom);              while(exclusion == 1);
     }              exclusion = 1;
   
               if ((*s_etat_processus).var_volatile_requete_arret == -1)
               {
                   deverrouillage_gestionnaire_signaux(s_etat_processus);
                   exclusion = 0;
                   return;
               }
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)              if ((*s_etat_processus).langue == 'F')
     {              {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  printf("+++Interruption\n");
         return;              }
     }              else
               {
                   printf("+++Interrupt\n");
               }
   
     if ((semaphore_global = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,              fflush(stdout);
             1)) == SEM_FAILED)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_semaphore;  
         return;  
     }  
   
     free(nom);              (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
     markov = 0;              exclusion = 0;
           }
       }
       else
       {
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigint);
           }
       }
   
       deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  static inline void
 liberation_fifos_signaux(struct_processus *s_etat_processus)  signal_tstp(struct_processus *s_etat_processus, pid_t pid)
 {  {
     int                 i;      struct_processus        *s_thread_principal;
   
 #   ifdef IPCS_SYSV // SystemV      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if (shmdt(fifos) == -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
            */
   
 #   else // POSIX          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 (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))          if ((*s_etat_processus).var_volatile_processus_pere == 0)
             != 0)          {
     {              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                      rpl_sigtstp);
         return;          }
           else
           {
               (*s_etat_processus).var_volatile_requete_arret2 = -1;
           }
     }      }
       else
 #   endif  
   
     for(i = 0; i < nombre_queues; i++)  
     {      {
         if (sem_close(semaphores[i]) != 0)          // Envoi d'un signal au thread maître du groupe.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
             return;  
         }          }
     }      }
   
     if (sem_close(semaphore_global) != 0)      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   static void
   sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
   {
       switch((*((volatile int *) arg1)))
     {      {
         (*s_etat_processus).erreur_systeme = d_es_semaphore;          case 1:
         return;              longjmp(contexte_ecriture, -1);
               break;
   
           case 2:
               longjmp(contexte_impression, -1);
               break;
     }      }
   
     return;      return;
 }  }
   
 void  void
 destruction_fifos_signaux(struct_processus *s_etat_processus)  interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
 {  {
     int                 i;      if ((urgence == 0) && (routine_recursive != 0))
       {
           // On peut tenter de récupérer le dépassement de pile. Si la variable
           // 'routine_recursive' est non nulle, on récupère l'erreur.
   
     unsigned char       *nom;          sigsegv_leave_handler(sortie_interruption_depassement_pile,
                   (void *) &routine_recursive, NULL, NULL);
       }
   
 #   ifdef IPCS_SYSV // SystemV      // Ici, la panique est totale et il vaut mieux quitter l'application.
       interruption3(SIGUSR2);
       return;
   }
   
   int
   interruption_violation_access(void *adresse_fautive, int gravite)
   {
       unsigned char       message[] = "+++System : Trying to catch access "
                                   "violation\n";
   
       static int          compteur_erreur = 0;
   
     if (shmdt(fifos) == -1)      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;  
           sigsegv_leave_handler(sortie_interruption_depassement_pile,
                   (void *) &routine_recursive, NULL, NULL);
     }      }
   
     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);
     }      }
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,      write(STDERR_FILENO, message, strlen(message));
             getpid())) == NULL)  
       if (pid_processus_pere == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          longjmp(contexte_initial, -1);
         return;          return(1);
       }
       else
       {
           longjmp(contexte_processus, -1);
           return(1);
     }      }
   
     unlink(nom);      // On renvoie 0 parce qu'on décline toute responsabilité quant à la
     free(nom);      // suite des événements...
       return(0);
   }
   
   // Traitement de rpl_sigstart
   
 #   else // POSIX  static inline void
   signal_start(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))      verrouillage_gestionnaire_signaux(s_etat_processus);
             != 0)  
       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(NULL, 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);
           }
     }      }
   
     if (shm_unlink(nom) != 0)      deverrouillage_gestionnaire_signaux(s_etat_processus);
       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 (pid == getpid())
     {      {
         free(nom);          (*s_etat_processus).redemarrage_processus = d_vrai;
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;      }
         return;      else
       {
           // Envoi d'un signal au thread maître du groupe.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigcont);
           }
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
 #   endif  // Traitement de rpl_sigstop
   
   static inline void
   signal_stop(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     for(i = 0; i < nombre_queues; i++)      verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
             return;                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
   
         if (sem_unlink(nom) != 0)          /*
            * 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)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              (*s_etat_processus).var_volatile_requete_arret = -1;
             return;          }
           else
           {
               (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
         }          }
       }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
         free(nom);          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigstop);
           }
     }      }
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   // Traitement de rpl_siginject
   
   static inline void
   signal_inject(struct_processus *s_etat_processus, pid_t pid)
   {
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          deverrouillage_gestionnaire_signaux(s_etat_processus);
         return;          return;
     }      }
   
     if (sem_unlink(nom) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_semaphore;          printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
         return;                  (unsigned long long) pthread_self());
           fflush(stdout);
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
   
     return;      return;
 }  }
   
 inline int  
 horodatage()  
 {  
     int             ts;  
   
     struct timeval  tv;  static inline void
   signal_urg(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     gettimeofday(&tv, NULL);      verrouillage_gestionnaire_signaux(s_etat_processus);
     ts = (int) ((tv.tv_sec * 100) + (tv.tv_usec / 10000));  
   
     return(ts);      if (pid == getpid())
 }      {
           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);
           }
   
 int          (*s_etat_processus).var_volatile_alarme = -1;
 queue_in(pid_t pid, int signal)          (*s_etat_processus).var_volatile_requete_arret = -1;
 {      }
     int             queue;      else
     int             *base;      {
     int             *buffer;          // Envoi d'un signal au thread maître du groupe.
     int             horodatage_initial;  
     int             identifiant;  
     int             *projection_fifos;  
   
     sem_t           *semaphore;          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigurg);
           }
       }
   
     queue = queue_de_signal(signal);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
     unsigned char   *nom;  // Traitement de rpl_sigabort
   
 #   ifndef IPCS_SYSV  static inline void
   signal_abort(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     // Ouverture des projections      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((nom = nom_segment(NULL, pid)) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         return(-1);          deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
     }      }
   
     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     // il convient d'attendre que le fichier support soit effectivement      {
     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il          printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
     // n'existe plus, le processus associé n'existe plus.                  (unsigned long long) pthread_self());
           fflush(stdout);
       }
   
     if (signal == SIGSTART)      if (pid == getpid())
     {      {
         horodatage_initial = horodatage();          (*s_etat_processus).arret_depuis_abort = -1;
   
           /*
            * 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)
            */
   
         while((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)          if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
         {          {
             if (abs(horodatage_initial - horodatage()) > 500)              (*s_etat_processus).var_volatile_requete_arret = -1;
             {          }
                 return(-1);          else
             }          {
               (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
         }          }
     }      }
     else      else
     {      {
         if ((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)          (*s_etat_processus).arret_depuis_abort = -1;
   
           // Envoi d'un signal au thread maître du groupe.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             return(-1);              envoi_signal_contexte(s_thread_principal, rpl_sigabort);
         }          }
     }      }
   
     projection_fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4)      deverrouillage_gestionnaire_signaux(s_etat_processus);
             * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, identifiant, 0);      return;
     close(identifiant);  }
   
     if (((void *) projection_fifos) == ((void *) -1))  
     {  
         return(-1);  
     }  
   
 #   else // Traitement à l'aide d'IPCS SystemV  
   
     key_t           clef;  static inline void
   signal_hup(struct_processus *s_etat_processus, pid_t pid)
   {
       file                    *fichier;
   
     struct stat     s_stat;      unsigned char           nom[8 + 64 + 1];
   
     // Ouverture des projections      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;
     }      }
   
     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,      snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
     // il convient d'attendre que le fichier support soit effectivement              (unsigned long long) getpid(),
     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il              (unsigned long long) pthread_self());
     // n'existe plus, le processus associé n'existe plus.  
   
     if (signal == SIGSTART)      if ((fichier = fopen(nom, "w+")) != NULL)
     {      {
         // On attend que le fichier sois présent          fclose(fichier);
   
         horodatage_initial = horodatage();  
   
         while(stat(nom, &s_stat) != 0)          freopen(nom, "w", stdout);
         {          freopen(nom, "w", stderr);
             if (abs(horodatage_initial - horodatage()) > 500)  
             {  
                 return(-1);  
             }  
         }  
     }      }
   
     if ((clef = ftok(nom, 1)) == -1)      freopen("/dev/null", "r", stdin);
   
       if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         return(-1);          printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
                   (unsigned long long) pthread_self());
           fflush(stdout);
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
     if (signal == SIGSTART)  void
     {  traitement_exceptions_gsl(const char *reason, const char *file,
         while((identifiant = shmget(clef,          int line, int gsl_errno)
                 nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),  {
                 S_IRUSR | S_IWUSR)) == -1);      code_erreur_gsl = gsl_errno;
     }      envoi_signal_processus(getpid(), rpl_sigexcept);
     else      return;
     {  }
         if ((identifiant = shmget(clef,  
                 nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),  
                 S_IRUSR | S_IWUSR)) == -1)  
         {  
             return(-1);  
         }  
     }  
   
     projection_fifos = shmat(identifiant, NULL, 0);  static inline void
   signal_except(struct_processus *s_etat_processus, pid_t pid)
   {
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if (((void *) projection_fifos) == ((void *) -1))      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         return(-1);          deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
     }      }
   
 #   endif      (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
       deverrouillage_gestionnaire_signaux(s_etat_processus);
   
     if ((nom = nom_semaphore(pid, queue)) == NULL)      return;
   }
   
   static inline void
   envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
           pid_t pid_source)
   {
       switch(signal)
     {      {
 #       ifdef IPCS_SYSV          case rpl_signull:
         shmdt(projection_fifos);              break;
 #       else  
         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)  
                 * sizeof(int));  
 #       endif  
         return(-1);  
     }  
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);          case rpl_sigint:
     free(nom);              signal_int(s_etat_processus, pid_source);
               break;
   
     while(sem_wait(semaphore) != 0)          case rpl_sigterm:
     {              signal_term(s_etat_processus, pid_source);
         if (errno != EINTR)              break;
         {  
 #           ifdef IPCS_SYSV  
             shmdt(projection_fifos);  
 #           else  
             munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)  
                     * sizeof(int));  
 #           endif  
             return(-1);  
         }  
     }  
   
     base = &(projection_fifos[(longueur_queue + 4) * queue]);          case rpl_sigstart:
     buffer = &(base[4]);              signal_start(s_etat_processus, pid_source);
               break;
   
     // base[3] contient le nombre d'éléments restants          case rpl_sigcont:
               signal_cont(s_etat_processus, pid_source);
               break;
   
     if (base[3] <= 0)          case rpl_sigstop:
     {              signal_stop(s_etat_processus, pid_source);
         sem_post(semaphore);              break;
         sem_close(semaphore);  
 #       ifdef IPCS_SYSV  
         shmdt(projection_fifos);  
 #       else  
         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)  
                 * sizeof(int));  
 #       endif  
         return(-1);  
     }  
   
     base[3]--;          case rpl_sigabort:
               signal_abort(s_etat_processus, pid_source);
               break;
   
     // base[1] contient le prochain élément à écrire          case rpl_sigurg:
               signal_urg(s_etat_processus, pid_source);
               break;
   
     buffer[base[1] + (nombre_queues * base[2])] = horodatage();          case rpl_siginject:
     buffer[base[1]++] = (int) pid;              signal_inject(s_etat_processus, pid_source);
     base[1] %= base[2];              break;
   
     if (sem_post(semaphore) != 0)          case rpl_sigalrm:
     {              signal_alrm(s_etat_processus, pid_source);
 #       ifdef IPCS_SYSV              break;
         shmdt(projection_fifos);  
 #       else  
         munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)  
                 * sizeof(int));  
 #       endif  
         sem_close(semaphore);  
         return(-1);  
     }  
   
     sem_close(semaphore);          case rpl_sighup:
               signal_hup(s_etat_processus, pid_source);
               break;
   
     // Fermeture des projections          case rpl_sigtstp:
 #   ifdef IPCS_SYSV              signal_tstp(s_etat_processus, pid_source);
     shmdt(projection_fifos);              break;
 #   else  
     munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)  
             * sizeof(int));  
 #   endif  
   
     return(0);          case rpl_sigexcept:
 }              signal_except(s_etat_processus, pid_source);
               break;
   
 inline int          default:
 chaine_markov(int markov, int delta)              if ((*s_etat_processus).langue == 'F')
 {              {
     double      memoire = 0.9;                  printf("+++System : Signal inconnu (%d) !\n", signal);
     int         valeur;              }
               else
               {
                   printf("+++System : Spurious signal (%d) !\n", signal);
               }
   
     valeur = (int) ((memoire * markov) + ((1 - memoire) * delta));              break;
     valeur = (valeur < 10) ? 10 : valeur;      }
   
     return(valeur);      return;
 }  }
   
 pid_t  void
 origine_signal(int signal)  scrutation_interruptions(struct_processus *s_etat_processus)
 {  {
     logical1        drapeau;      // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
     int             *base;  
     int             *buffer;  
     int             delta;  
     int             pid;  
     int             queue;  
   
     queue = queue_de_signal(signal);  
   
     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",      // Les pointeurs de lecture pointent sur les prochains éléments
             (int) getpid(), signal));      // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
       // écrire.
   
     while(sem_wait(semaphores[queue]) != 0)  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
           if (sem_trywait(&((*s_queue_signaux).semaphore)) == 0)
   #   else
           if (sem_trywait(semaphore_queue_signaux) == 0)
   #   endif
     {      {
         if (errno != EINTR)          while((*s_queue_signaux).pointeur_lecture !=
                   (*s_queue_signaux).pointeur_ecriture)
         {          {
             return(-1);              // Il y a un signal en attente dans le segment partagé. On le
               // traite.
   
               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;
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               while(sem_wait(&((*s_queue_signaux).signalisation)) != 0)
   #           else
               while(sem_wait(semaphore_signalisation) != 0)
   #           endif
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                       return;
                   }
               }
         }          }
     }  
   
     // On retire les interruptions anciennes qui ont été ratées sauf s'il  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     // s'agit de la dernière dans la queue.              sem_post(&((*s_queue_signaux).semaphore));
   #       else
               sem_post(semaphore_queue_signaux);
   #       endif
       }
   
     base = &(fifos[(longueur_queue + 4) * queue]);      // Interruptions qui arrivent depuis le groupe courant de threads.
     buffer = &(base[4]);  
   
     if (base[3] == (base[2] - 1))      if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
     {      {
         delta = abs(horodatage() -          while((*s_etat_processus).pointeur_signal_lecture !=
                  buffer[base[0] + (nombre_queues * base[2])]);                  (*s_etat_processus).pointeur_signal_ecriture)
         // Une seule interruption dans la queue.          {
         pid = buffer[base[0]++];              // Il y a un signal dans la queue du thread courant. On le traite.
         base[0] %= base[2];  
         base[3]++;  
   
         markov = chaine_markov(markov, delta);              envoi_interruptions(s_etat_processus,
     }                      (*s_etat_processus).signaux_en_queue
     else if (base[3] >= base[2])                      [(*s_etat_processus).pointeur_signal_lecture],
     {                      getpid());
         // Aucune interruption n'est dans la queue.              (*s_etat_processus).pointeur_signal_lecture =
         // On a retiré trop d'interruptions de la queue.                      ((*s_etat_processus).pointeur_signal_lecture + 1)
                       % LONGUEUR_QUEUE_SIGNAUX;
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               while(sem_wait(&((*s_queue_signaux).signalisation)) != 0)
   #           else
               while(sem_wait(semaphore_signalisation) != 0)
   #           endif
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                       return;
                   }
               }
           }
   
         // (base[3] - base[2]) + 1 : nombre d'interruptions manquantes          pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
         // base[0] - 1             : dernière interruption lue  
         pid = buffer[((((base[0] + base[2] - 1) % base[2])  
                 - ((base[3] - base[2]) + 1)) + base[2]) % base[2]];  
     }      }
     else  
     {  
         // Plusieurs interruptions à distribuer.  
         drapeau = d_vrai;  
   
         do      return;
         {  }
             delta = abs(horodatage() -  
                      buffer[base[0] + (nombre_queues * base[2])]);  /*
             pid = buffer[base[0]++];  ================================================================================
             base[0] %= base[2];    Fonction renvoyant le nom du segment de mémoire partagée en fonction
             base[3]++;    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 ((delta > (2 * markov)) && (base[3] < base[2]))              if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *
                       sizeof(unsigned char))) == NULL)
             {              {
                 drapeau = d_vrai;                  return(NULL);
             }              }
             else  
               sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
   #       else // OS2
               if ((fichier = malloc((10 + 256 + 1) * sizeof(unsigned char)))
                       == NULL)
             {              {
                 drapeau = d_faux;                  return(NULL);
             }              }
         } while(drapeau == d_vrai);  
   
         markov = chaine_markov(markov, delta);              sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
     }  #       endif // OS2
   #   else // POSIX
   
     if (sem_post(semaphores[queue]) != 0)          if ((fichier = malloc((1 + 256 + 1) *
     {                  sizeof(unsigned char))) == NULL)
         return(-1);          {
     }              return(NULL);
           }
   
           sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
   #   endif
   
     return((pid_t) pid);      return(fichier);
 }  }
   
 #endif  
   
 void  /*
 interruption1(SIGHANDLER_ARGS)  ================================================================================
     Fonctions d'envoi d'un signal à un thread ou à un processus.
   ================================================================================
     Entrée : processus et signal
   --------------------------------------------------------------------------------
     Sortie : erreur
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   int
   envoi_signal_processus(pid_t pid, enum signaux_rpl signal)
 {  {
     pid_t                   pid;  #   ifndef OS2
           int                         segment;
   #   endif
   
     pthread_t               thread;  #   ifndef IPCS_SYSV
   #       ifdef SEMAPHORES_NOMMES
               sem_t                   *semaphore;
               sem_t                   *signalisation;
   #       endif
   #   else
   #       ifndef OS2
               int                     desc;
               key_t                   clef;
   #       endif
   #   endif
   
     struct_processus        *s_etat_processus;      struct_queue_signaux            *queue;
   
     volatile sig_atomic_t   exclusion = 0;      unsigned char                   *nom;
   
     verrouillage_gestionnaire_signaux();      // 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.
   
 #   ifdef _BROKEN_SIGINFO      if (pid == getpid())
     if (signal == SIGINT)  
     {      {
         // Si l'interruption provient du clavier, il n'y a pas eu d'appel          // Le signal est envoyé au même processus.
         // à queue_in().  
           if (s_queue_signaux == NULL)
           {
               return(1);
           }
   
         pid = getpid();  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               while(sem_wait(&((*s_queue_signaux).semaphore)) != 0)
   #       else
               while(sem_wait(semaphore_queue_signaux) != 0)
   #       endif
           {
               if (errno != EINTR)
               {
                   return(1);
               }
           }
   
           (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .pid = pid;
           (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .signal = signal;
   
           (*s_queue_signaux).pointeur_ecriture =
                   ((*s_queue_signaux).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
   #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               if (sem_post(&((*s_queue_signaux).semaphore)) != 0)
   #       else
               if (sem_post(semaphore_queue_signaux) != 0)
   #       endif
           {
               return(1);
           }
   
   #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
   #       else
               if (sem_post(semaphore_signalisation) != 0)
   #       endif
           {
               return(1);
           }
     }      }
     else      else
     {      {
         pid = origine_signal(signal);          // Le signal est envoyé depuis un processus distinct.
     }  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     switch(signal)  #       ifdef IPCS_SYSV
     {              if ((nom = nom_segment(racine_segment, pid)) == NULL)
         case SIGALRM :  
         {  
             if (pid == getpid())  
             {              {
                 if ((s_etat_processus = recherche_thread(getpid(),                  return(1);
                         pthread_self())) == NULL)              }
   
   #           ifndef OS2 // SysV
                   if ((desc = open(nom, O_RDWR)) == -1)
                 {                  {
                     deverrouillage_gestionnaire_signaux();                      free(nom);
                      return;                      return(1);
                 }                  }
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)                  close(desc);
   
                   if ((clef = ftok(nom, 1)) == -1)
                 {                  {
                     printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(),                      free(nom);
                             (unsigned long long) pthread_self());                      return(1);
                     fflush(stdout);  
                 }                  }
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())                  free(nom);
   
                   if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
                           == -1)
                 {                  {
                     kill((*s_etat_processus).pid_processus_pere, signal);                      return(1);
                 }                  }
                 else  
                   queue = shmat(segment, NULL, 0);
   #           else // OS/2
                   if (DosGetNamedSharedMem((PVOID) &queue, nom,
                           PAG_WRITE | PAG_READ) != 0)
                 {                  {
                     (*s_etat_processus).var_volatile_alarme = -1;                      free(nom);
                     (*s_etat_processus).var_volatile_requete_arret = -1;                      return(1);
                 }                  }
             }  
             else                  free(nom);
   #           endif
   #       else // POSIX
               if ((nom = nom_segment(racine_segment, pid)) == NULL)
             {              {
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)                  return(1);
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }              }
   
             break;              if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
         }              {
                   free(nom);
                   return(1);
               }
   
         case SIGINT :              free(nom);
         {  
             /*  
              * Une vieille spécification POSIX permet au pointeur siginfo  
              * d'être nul dans le cas d'un ^C envoyé depuis le clavier.  
              * Solaris suit en particulier cette spécification.  
              */  
   
 #           ifndef _BROKEN_SIGINFO              if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
             if (siginfo == NULL)                      PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
                       MAP_FAILED)
             {              {
                 kill(getpid(), signal);                  close(segment);
                   return(1);
             }              }
             else  #       endif
 #           endif  
             if (pid == getpid())              // À ce moment, le segment de mémoire partagée est projeté
             {              // dans l'espace du processus.
                 if ((s_etat_processus = recherche_thread(getpid(),  
                         pthread_self())) == NULL)  #       ifndef IPCS_SYSV // POSIX
   #           ifndef SEMAPHORES_NOMMES
                   while(sem_wait(&((*queue).semaphore)) != 0)
                 {                  {
                     deverrouillage_gestionnaire_signaux();                      if (errno != EINTR)
                     return;                      {
                           return(1);
                       }
                   }
   #           else
                   if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
                   {
                       return(1);
                 }                  }
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)                  if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
                           == SEM_FAILED)
                 {                  {
                     printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),                      return(1);
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }                  }
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())                  while(sem_wait(semaphore) != 0)
                 {                  {
                     kill((*s_etat_processus).pid_processus_pere, signal);                      if (errno != EINTR)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           return(1);
                       }
                 }                  }
                 else  #           endif
   #       else // IPCS_SYSV
               while(sem_wait(&((*queue).semaphore)) != 0)
               {
                   if (errno != EINTR)
                 {                  {
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;                      return(1);
                   }
               }
   #       endif
   
                     while(exclusion == 1);          (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
                     exclusion = 1;          (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)          (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
                     {                  % LONGUEUR_QUEUE_SIGNAUX;
                         deverrouillage_gestionnaire_signaux();  
                         exclusion = 0;  
                         return;  
                     }  
   
                     if (strncmp(getenv("LANG"), "fr", 2) == 0)  #       ifndef IPCS_SYSV // POSIX
                     {  #           ifndef SEMAPHORES_NOMMES
                         printf("+++Interruption\n");                  if (sem_post(&((*queue).semaphore)) != 0)
                     }                  {
                     else                      return(1);
                     {                  }
                         printf("+++Interrupt\n");  
                     }  
   
                     fflush(stdout);                  if (sem_post(&((*queue).signalisation)) != 0)
                   {
                       return(1);
                   }
   #           else
                   if (sem_post(semaphore) != 0)
                   {
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;                  if (sem_close(semaphore) != 0)
                     (*s_etat_processus).var_volatile_alarme = -1;                  {
                       return(1);
                   }
   
                     exclusion = 0;                  if (sem_post(signalisation) != 0)
                   {
                       sem_close(signalisation);
                       return(1);
                 }                  }
             }  
             else                  if (sem_close(signalisation) != 0)
             {  
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
                 {                  {
                     pthread_kill(thread, signal);                      return(1);
                 }                  }
   
   #           endif
   
               if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
               {
                   close(segment);
                   return(1);
               }
   #       else // IPCS_SYSV
               if (sem_post(&((*queue).semaphore)) != 0)
               {
                   return(1);
             }              }
   
             break;              if (sem_post(&((*queue).signalisation)) != 0)
         }              {
                   return(1);
               }
   
         default :  #           ifndef OS2 // SysV
         {                  if (shmdt(queue) != 0)
             BUG(1, uprintf("[%d] Unknown signal %d in this context\n",                  {
                     (int) getpid(), signal));                      return(1);
             break;                  }
         }  #           else // OS/2
                   // Pendant de DosGetNamedSHaredMem()
   #           endif
   #       endif
     }      }
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  int
 interruption2(SIGHANDLER_ARGS)  envoi_signal_thread(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;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO      struct_processus                        *s_etat_processus;
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
 #   ifndef _BROKEN_SIGINFO      if (pthread_mutex_lock(&mutex_liste_threads) != 0)
     if (siginfo == NULL)  
     {      {
         /*          return(1);
          * 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)  
         {  
             pthread_kill(thread, SIGHUP);  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
     }      }
     else  
 #   endif  
     if (pid == getpid())  
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         /*      l_element_courant = liste_threads;
          *  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)      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))
         {          {
             printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(),              break;
                     (unsigned long long) pthread_self());  
             fflush(stdout);  
         }          }
   
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          l_element_courant = (*l_element_courant).suivant;
         {  
             kill((*s_etat_processus).pid_processus_pere, signal);  
         }  
         else  
         {  
             (*s_etat_processus).var_volatile_requete_arret2 = -1;  
         }  
     }      }
     else  
     {  
         // Envoi d'un signal au thread maître du groupe.  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)      if (l_element_courant == NULL)
         {      {
             pthread_kill(thread, SIGTSTP);          pthread_mutex_unlock(&mutex_liste_threads);
             deverrouillage_gestionnaire_signaux();          return(1);
             return;  
         }  
     }      }
   
     deverrouillage_gestionnaire_signaux();      s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
     return;              .s_etat_processus;
 }  
   
 void  
 interruption3(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     static int              compteur = 0;      if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
       {
     verrouillage_gestionnaire_signaux();          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;
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
     {      {
         deverrouillage_gestionnaire_signaux();          pthread_mutex_unlock(&mutex_liste_threads);
         return;          return(1);
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     {      {
         printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(),          return(1);
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   
     if ((*s_etat_processus).var_volatile_recursivite == -1)  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
     {      {
         // Segfault dans un appel de fonction récursive          return(1);
         deverrouillage_gestionnaire_signaux();  
         longjmp(contexte, -1);  
     }      }
     else  #   else
       if (sem_post(semaphore_signalisation) != 0)
     {      {
         // Segfault dans une routine interne          return(1);
         if (strncmp(getenv("LANG"), "fr", 2) == 0)  
         {  
             printf("+++Système : Violation d'accès (dépassement de pile)\n");  
         }  
         else  
         {  
             printf("+++System : Access violation (stack overflow)\n");  
         }  
   
         fflush(stdout);  
   
         compteur++;  
   
         if (compteur > 1)  
         {  
             deverrouillage_gestionnaire_signaux();  
             exit(EXIT_FAILURE);  
         }  
         else  
         {  
             deverrouillage_gestionnaire_signaux();  
             longjmp(contexte_initial, -1);  
         }  
     }      }
   #   endif
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  int
 interruption4(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;
       (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
               ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
               % LONGUEUR_QUEUE_SIGNAUX;
       pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
   
     verrouillage_gestionnaire_signaux();  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  
     {      {
         deverrouillage_gestionnaire_signaux();          return(1);
         return;  
     }      }
   #   else
     /*      if (sem_post(semaphore_signalisation) != 0)
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)  
      */  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
     {      {
         printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),          return(1);
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   #   endif
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  
 interruption5(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  /*
   ================================================================================
     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
   ================================================================================
   */
   
     struct_processus        *s_etat_processus;  void
   creation_queue_signaux(struct_processus *s_etat_processus)
   {
       pthread_attr_t                  attributs;
   
     verrouillage_gestionnaire_signaux();      unsigned char                   *nom;
   
 #   ifdef _BROKEN_SIGINFO      racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if (pid == getpid())  #   ifndef IPCS_SYSV // POSIX
     {          if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))                  getpid())) == NULL)
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
                   S_IRUSR | S_IWUSR)) == -1)
         {          {
             printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),              free(nom);
                     (unsigned long long) pthread_self());              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             fflush(stdout);              return;
         }          }
   
         /*          if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
          * 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)  
         {  
             (*s_etat_processus).var_volatile_requete_arret = -1;  
         }  
         else  
         {  
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;  
         }  
     }  
     else  
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         // Envoi d'un signal au thread maître du groupe.          s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
                   PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if (((void *) s_queue_signaux) == ((void *) -1))
         {          {
             pthread_kill(thread, signal);              if (shm_unlink(nom) == -1)
             deverrouillage_gestionnaire_signaux();              {
                   free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
     }  
   
     deverrouillage_gestionnaire_signaux();          free(nom);
     return;  
 }  
   
 void  #       ifndef SEMAPHORES_NOMMES
 interruption6(SIGHANDLER_ARGS)              sem_init(&((*s_queue_signaux).semaphore), 1, 1);
 {              sem_init(&((*s_queue_signaux).signalisation), 1, 0);
     pid_t                   pid;              sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
   #       else
               if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
                       == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
     struct_processus        *s_etat_processus;              if ((semaphore_signalisation = sem_init2(0, getpid(),
                       SEM_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
     verrouillage_gestionnaire_signaux();              if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
                       SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   #       endif
   
 #   ifdef _BROKEN_SIGINFO          (*s_queue_signaux).pointeur_lecture = 0;
     pid = origine_signal(signal);          (*s_queue_signaux).pointeur_ecriture = 0;
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)          (*s_queue_signaux).requete_arret = d_faux;
     {  
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (msync(s_queue_signaux, sizeof(struct_queue_signaux), MS_SYNC))
     {          {
         printf("[%d] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(),              (*s_etat_processus).erreur_systeme = d_es_processus;
                 (unsigned long long) pthread_self());              return;
         fflush(stdout);          }
     }  #   else // IPCS_SYSV
   #       ifndef OS2
               int                             segment;
               int                             support;
   
     deverrouillage_gestionnaire_signaux();              key_t                           clef;
     return;  
 }  
   
 void              // Création d'un segment de données associé au PID du processus
 interruption7(SIGHANDLER_ARGS)              // courant
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;              if ((nom = nom_segment((*s_etat_processus)
                       .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     verrouillage_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)
     pid = origine_signal(signal);              {
 #   else                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
     pid = (*siginfo).si_pid;                  return;
 #   endif              }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)              close(support);
     {              free(nom);
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              if ((segment = shmget(clef, sizeof(struct_queue_signaux),
     {                      IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),              {
                 (unsigned long long) pthread_self());                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         fflush(stdout);                  return;
     }              }
   
     (*s_etat_processus).var_volatile_requete_arret = -1;              s_queue_signaux = shmat(segment, NULL, 0);
     deverrouillage_gestionnaire_signaux();              f_queue_signaux = segment;
   
     BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));              if (((void *) s_queue_signaux) == ((void *) -1))
     return;              {
 }                  if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return;
                   }
   
 void                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 interruption8(SIGHANDLER_ARGS)                  return;
 {              }
     pid_t                   pid;  
   
     pthread_t               thread;              sem_init(&((*s_queue_signaux).semaphore), 1, 1);
               sem_init(&((*s_queue_signaux).signalisation), 1, 0);
               sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
   
               (*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;
               }
   
     struct_processus        *s_etat_processus;              if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
                       sizeof(struct_queue_signaux),
                       PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
               {
                   free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     verrouillage_gestionnaire_signaux();              free(nom);
   
 #   ifdef _BROKEN_SIGINFO              sem_init(&((*s_queue_signaux).semaphore), 1, 1);
     pid = origine_signal(signal);              sem_init(&((*s_queue_signaux).signalisation), 1, 0);
 #   else              sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
     pid = (*siginfo).si_pid;  
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       endif
 #   endif  #   endif
   
     if (pid == getpid())      // Lancement du thread de récupération des signaux.
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
         {  
             printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),  
                     (unsigned long long) pthread_self());  
             fflush(stdout);  
         }  
   
         (*s_etat_processus).var_volatile_alarme = -1;      if (pthread_attr_init(&attributs) != 0)
         (*s_etat_processus).var_volatile_requete_arret = -1;  
     }  
     else  
     {      {
         // Envoi d'un signal au thread maître du groupe.          (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
         {  
             pthread_kill(thread, SIGURG);  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
     }      }
   
     deverrouillage_gestionnaire_signaux();      if (pthread_attr_setdetachstate(&attributs,
     return;              PTHREAD_CREATE_JOINABLE) != 0)
 }  
   
 void  
 interruption9(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), 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)  #   ifdef SCHED_OTHER
       if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0)
     {      {
         printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),          (*s_etat_processus).erreur_systeme = d_es_processus;
                 (unsigned long long) pthread_self());          return;
         fflush(stdout);  
     }      }
   #   endif
   
 #   ifdef _BROKEN_SIGINFO  #   ifdef PTHREAD_EXPLICIT_SCHED
     if (queue_in(getpid(), signal) != 0)      if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0)
     {      {
           (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     deverrouillage_gestionnaire_signaux();  
     interruption11(signal);  
 #   else  
     deverrouillage_gestionnaire_signaux();  
     interruption11(signal, siginfo, context);  
 #   endif  
     return;  
 }  
   
 void  
 interruption10(SIGHANDLER_ARGS)  
 {  
     file                    *fichier;  
   
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     unsigned char           nom[8 + 64 + 1];  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  #   endif
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  #   ifdef PTHREAD_SCOPE_SYSTEM
       if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0)
     {      {
         deverrouillage_gestionnaire_signaux();          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   #   endif
   
     snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),      if (pthread_attr_destroy(&attributs) != 0)
             (unsigned long) pthread_self());  
   
     if ((fichier = fopen(nom, "w+")) != NULL)  
     {      {
         fclose(fichier);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
         freopen(nom, "w", stdout);  
         freopen(nom, "w", stderr);  
     }      }
   
     freopen("/dev/null", "r", stdin);      if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
               thread_surveillance_signaux, s_etat_processus) != 0)
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 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();  
     return;      return;
 }  }
   
 void  
 interruption11(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  /*
   ================================================================================
     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
   ================================================================================
   */
   
     struct_processus        *s_etat_processus;  void
   liberation_queue_signaux(struct_processus *s_etat_processus)
   {
   #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       sem_wait(&((*s_queue_signaux).arret_signalisation));
   #   else
       sem_wait(semaphore_arret_signalisation);
   #   endif
   
     verrouillage_gestionnaire_signaux();      (*s_queue_signaux).requete_arret = d_vrai;
   
 #   ifdef _BROKEN_SIGINFO  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     pid = origine_signal(signal);      sem_post(&((*s_queue_signaux).arret_signalisation));
 #   else  #   else
     pid = (*siginfo).si_pid;      sem_post(semaphore_arret_signalisation);
 #   endif  #   endif
   
     if (pid == getpid())      // Incrémenter le sémaphore pour être sûr de le débloquer.
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         (*s_etat_processus).arret_depuis_abort = -1;  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       sem_post(&((*s_queue_signaux).signalisation));
   #   else
       sem_post(semaphore_signalisation);
   #   endif
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      pthread_join((*s_queue_signaux).thread_signaux, NULL);
         {  
             printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(),  
                     (unsigned long long) pthread_self());  
             fflush(stdout);  
         }  
   
         /*  #   ifdef IPCS_SYSV // SystemV
          * var_globale_traitement_retarde_stop :  #       ifndef OS2
          *  0 -> traitement immédiat              if (shmdt(s_queue_signaux) == -1)
          *  1 -> traitement retardé (aucun signal reçu)              {
          * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
          */                  return;
               }
   #       else // OS/2
   #       endif
   #   else // POSIX
   #       ifndef SEMAPHORES_NOMMES
               // Rien à faire, les sémaphores sont anonymes.
   #       else
               sem_close(semaphore_queue_signaux);
               sem_close(semaphore_signalisation);
               sem_close(semaphore_arret_signalisation);
   #       endif
   
         if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)          if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
         {  
             (*s_etat_processus).var_volatile_requete_arret = -1;  
         }  
         else  
         {  
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;  
         }  
     }  
     else  
     {  
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {          {
             deverrouillage_gestionnaire_signaux();              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         (*s_etat_processus).arret_depuis_abort = -1;          close(f_queue_signaux);
   #   endif
         // Envoi d'un signal au thread maître du groupe.  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
         {  
             pthread_kill(thread, signal);  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
     }  
   
     deverrouillage_gestionnaire_signaux();  
     return;      return;
 }  }
   
   
   /*
   ================================================================================
     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  void
 traitement_exceptions_gsl(const char *reason, const char *file,  destruction_queue_signaux(struct_processus *s_etat_processus)
         int line, int gsl_errno)  
 {  {
     struct_processus        *s_etat_processus;  #   ifndef OS2
           unsigned char       *nom;
     verrouillage_gestionnaire_signaux();  #   endif
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     {      sem_wait(&((*s_queue_signaux).arret_signalisation));
         deverrouillage_gestionnaire_signaux();  #   else
         return;      sem_wait(semaphore_arret_signalisation);
     }  #   endif
   
     (*s_etat_processus).var_volatile_exception_gsl = gsl_errno;      (*s_queue_signaux).requete_arret = d_vrai;
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 #ifdef _BROKEN_SIGINFO  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       sem_post(&((*s_queue_signaux).arret_signalisation));
   #   else
       sem_post(semaphore_arret_signalisation);
   #   endif
   
 #undef kill      // Incrémenter le sémaphore pour être sûr de le débloquer.
 #undef pthread_kill  
   
 int  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
 kill_broken_siginfo(pid_t pid, int signal)      sem_post(&((*s_queue_signaux).signalisation));
 {  #   else
     int                 ios;      sem_post(semaphore_signalisation);
   #   endif
   
     sem_t               *semaphore;      pthread_join((*s_queue_signaux).thread_signaux, NULL);
   
     unsigned char       *nom;  #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
               // Il faut commencer par éliminer le sémaphore.
   
     /*              if (semctl((*s_queue_signaux).semaphore.sem, 0, IPC_RMID) == -1)
      * Lorsqu'on veut interrompre le processus pid, on ouvre le segment              {
      * correspondant au processus en question et ou ajoute le pid dans la                  (*s_etat_processus).erreur_systeme = d_es_processus;
      * queue.                  return;
      *              }
      * Le sémaphore global à tous les threads d'un même processus sert  
      * à garantir que les signaux seront traités dans l'ordre de ce qui est  
      * effectivement mis dans la queue.  
      */  
   
     // Sémaphore acquis              unlink((*s_queue_signaux).semaphore.path);
               free((*s_queue_signaux).semaphore.path);
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)              if (semctl((*s_queue_signaux).signalisation.sem, 0, IPC_RMID) == -1)
     {              {
         return(-1);                  (*s_etat_processus).erreur_systeme = d_es_processus;
     }                  return;
               }
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);              unlink((*s_queue_signaux).signalisation.path);
     free(nom);              free((*s_queue_signaux).signalisation.path);
   
     while(sem_wait(semaphore) != 0)              if (semctl((*s_queue_signaux).arret_signalisation.sem, 0, IPC_RMID)
     {                      == -1)
         if (errno != EINTR)              {
         {                  (*s_etat_processus).erreur_systeme = d_es_processus;
             return(-1);                  return;
         }              }
     }  
   
     if ((signal != 0) && (signal != SIGINT))              unlink((*s_queue_signaux).arret_signalisation.path);
     {              free((*s_queue_signaux).arret_signalisation.path);
         if (queue_in(pid, signal) != 0)  
         {  
             sem_post(semaphore);  
             sem_close(semaphore);  
             return(-1);  
         }  
     }  
   
     ios = kill(pid, signal);              if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     // Sémaphore relâché              if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     sem_post(semaphore);              if ((nom = nom_segment((*s_etat_processus)
     sem_close(semaphore);                      .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     return(ios);              unlink(nom);
 }              free(nom);
   #       else
               sem_close(&((*s_queue_signaux).semaphore));
               sem_destroy(&((*s_queue_signaux).semaphore));
   
 int              sem_close(&((*s_queue_signaux).signalisation));
 pthread_kill_broken_siginfo(pthread_t tid, int signal)              sem_destroy(&((*s_queue_signaux).signalisation));
 {  
     int                 ios;  
   
     sem_t               *semaphore;              sem_close(&((*s_queue_signaux).arret_signalisation));
               sem_destroy(&((*s_queue_signaux).arret_signalisation));
   
     unsigned char       *nom;              if (DosFreeMem(s_queue_signaux) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       endif
   #   else // POSIX
   #       ifndef SEMAPHORES_NOMMES
               sem_destroy(&((*s_queue_signaux).semaphore));
               sem_destroy(&((*s_queue_signaux).signalisation));
               sem_destroy(&((*s_queue_signaux).arret_signalisation));
   #       else
               sem_close(semaphore_queue_signaux);
               sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)              sem_close(semaphore_signalisation);
     {              sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
         return(-1);  
     }  
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);              sem_close(semaphore_arret_signalisation);
     free(nom);              sem_destroy2(semaphore_arret_signalisation, getpid(),
                       SEM_ARRET_SIGNALISATION);
   #       endif
   
     while(sem_wait(semaphore) != 0)          if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
     {  
         if (errno != EINTR)  
         {          {
             return(-1);              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
     }  
   
     if ((signal != 0) && (signal != SIGINT))          if ((nom = nom_segment(NULL, getpid())) == NULL)
     {  
         if (queue_in(getpid(), signal) != 0)  
         {          {
             sem_post(semaphore);              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             sem_close(semaphore);              return;
             return(-1);  
         }          }
     }  
   
     ios = pthread_kill(tid, signal);          close(f_queue_signaux);
   
           if (shm_unlink(nom) != 0)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     sem_post(semaphore);          free(nom);
     sem_close(semaphore);  #   endif
   
     return(ios);      return;
 }  }
   
 #endif  
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.35  
changed lines
  Added in v.1.140


CVSweb interface <joel.bertrand@systella.fr>