Diff for /rpl/src/interruptions.c between versions 1.66 and 1.121

version 1.66, 2011/09/10 20:45:06 version 1.121, 2013/03/21 11:30:30
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.1.3    RPL/2 (R) version 4.1.13
   Copyright (C) 1989-2011 Dr. BERTRAND Joël    Copyright (C) 1989-2013 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 pthread_mutex_t                          mutex_interruptions
           = PTHREAD_MUTEX_INITIALIZER;
   
   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)
               sem_post(&(*s_queue_signaux).signalisation);
   #           else
               sem_post(semaphore_signalisation);
   #           endif
   
               if ((*s_queue_signaux).requete_arret == d_vrai)
               {
                   break;
               }
   
               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.
   
               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())
                   {
                       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);
                       }
                   }
   
                   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 204  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 226  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 248  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_nombre_references));      pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references));
Line 192  insertion_thread_surveillance(struct_pro Line 272  insertion_thread_surveillance(struct_pro
   
     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 311  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 325  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 368  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 393  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 381  retrait_thread_surveillance(struct_proce Line 410  retrait_thread_surveillance(struct_proce
     if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))      if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
             != 0)              != 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 404  retrait_thread_surveillance(struct_proce Line 426  retrait_thread_surveillance(struct_proce
         if (pthread_mutex_unlock(&((*s_argument_thread)          if (pthread_mutex_unlock(&((*s_argument_thread)
                 .mutex_nombre_references)) != 0)                  .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 425  retrait_thread_surveillance(struct_proce Line 440  retrait_thread_surveillance(struct_proce
         if (pthread_mutex_unlock(&((*s_argument_thread)          if (pthread_mutex_unlock(&((*s_argument_thread)
                 .mutex_nombre_references)) != 0)                  .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 464  verrouillage_threads_concurrents(struct_ Line 461  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 486  verrouillage_threads_concurrents(struct_ Line 476  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 521  deverrouillage_threads_concurrents(struc Line 508  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;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     return;                      return;
                 }                  }
 #               else  
                 if (sem_post(semaphore_liste_threads) != 0)  
                 {  
                     (*s_etat_processus).erreur_systeme = d_es_processus;  
                     return;  
                 }  
 #               endif  
   
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 return;                  return;
Line 552  deverrouillage_threads_concurrents(struc Line 531  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 570  liberation_threads(struct_processus *s_e Line 545  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 586  liberation_threads(struct_processus *s_e Line 564  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 684  liberation_threads(struct_processus *s_e Line 651  liberation_threads(struct_processus *s_e
                         .mutex_nombre_references)) != 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 709  liberation_threads(struct_processus *s_e Line 676  liberation_threads(struct_processus *s_e
                             .mutex_nombre_references)) != 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 734  liberation_threads(struct_processus *s_e Line 701  liberation_threads(struct_processus *s_e
                             .mutex_nombre_references)) != 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 803  liberation_threads(struct_processus *s_e Line 770  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             liberation_arbre_variables(s_etat_processus,              // ne peut être effacé qu'une seule fois
                     (*s_etat_processus).s_arbre_variables, d_faux);  
   
             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;
                 }                  }
               }
   
                 pthread_mutex_trylock(&((*(*s_etat_processus)              liberation_arbre_variables(s_etat_processus,
                         .s_liste_variables_partagees).mutex));                      (*s_etat_processus).s_arbre_variables, d_faux);
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_partagees).mutex));              l_element_statique_courant = (*s_etat_processus)
                       .l_liste_variables_statiques;
   
               while(l_element_statique_courant != NULL)
               {
                   l_element_statique_suivant =
                       (*l_element_statique_courant).suivant;
                   free(l_element_statique_courant);
                   l_element_statique_courant = l_element_statique_suivant;
             }              }
   
             element_courant = (*s_etat_processus).l_base_pile;              element_courant = (*s_etat_processus).l_base_pile;
Line 1311  liberation_threads(struct_processus *s_e Line 1261  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);              liberation_contexte_cas(s_etat_processus);
Line 1345  liberation_threads(struct_processus *s_e Line 1295  liberation_threads(struct_processus *s_e
                 != 0)                  != 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 1319  liberation_threads(struct_processus *s_e
                     .mutex_nombre_references)) != 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 1393  liberation_threads(struct_processus *s_e Line 1343  liberation_threads(struct_processus *s_e
                     .mutex_nombre_references)) != 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 1405  liberation_threads(struct_processus *s_e Line 1355  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 1507  recherche_thread_principal(pid_t pid) Line 1450  recherche_thread_principal(pid_t pid)
 // 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;      int         semaphore;
   
     sigset_t    oldset;  #   ifndef SEMAPHORES_NOMMES
     sigset_t    set;      if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
   #   else
     sem_t       *sem;      if (sem_post((*s_etat_processus).semaphore_fork) != 0)
   #   endif
     if ((sem = pthread_getspecific(semaphore_fork_processus_courant))  
             != NULL)  
     {      {
         if (sem_post(sem) != 0)          BUG(1, uprintf("Lock error !\n"));
         {          return;
             BUG(1, uprintf("Lock error !\n"));  
             return;  
         }  
     }      }
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !      // Il faut respecteur l'atomicité des deux opérations suivantes !
   
     sigfillset(&set);      if (pthread_mutex_lock(&mutex_gestionnaires_signaux_atomique) != 0)
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)  
 #   else  
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)  #       ifndef SEMAPHORES_NOMMES
         {          sem_wait(&((*s_etat_processus).semaphore_fork));
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  #       else
             BUG(1, uprintf("Unlock error !\n"));          sem_wait((*s_etat_processus).semaphore_fork);
             return;  #       endif
         }          BUG(1, uprintf("Unlock error !\n"));
           return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
Line 1551  verrouillage_gestionnaire_signaux() Line 1483  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;
     }      }
Line 1562  verrouillage_gestionnaire_signaux() Line 1498  verrouillage_gestionnaire_signaux()
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)      if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)
 #   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      if (pthread_mutex_unlock(&mutex_gestionnaires_signaux_atomique) != 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);  #       ifndef SEMAPHORES_NOMMES
           sem_wait(&((*s_etat_processus).semaphore_fork));
   #       else
           sem_wait((*s_etat_processus).semaphore_fork);
   #       endif
         BUG(1, uprintf("Unlock error !\n"));          BUG(1, uprintf("Unlock error !\n"));
         return;          return;
     }      }
Line 1586  verrouillage_gestionnaire_signaux() Line 1526  verrouillage_gestionnaire_signaux()
         // par un thread concurrent. On essaye donc de le bloquer jusqu'à          // par un thread concurrent. On essaye donc de le bloquer jusqu'à
         // ce que ce soit possible.          // ce que ce soit possible.
   
 #       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)  #           ifndef SEMAPHORES_NOMMES
             {              sem_wait(&((*s_etat_processus).semaphore_fork));
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);  #           else
               sem_wait((*s_etat_processus).semaphore_fork);
                 while(sem_wait(sem) == -1)  #           endif
                 {              BUG(1, uprintf("Lock error !\n"));
                     if (errno != EINTR)              return;
                     {  
                         BUG(1, uprintf("Lock error !\n"));  
                         return;  
                     }  
                 }  
   
                 BUG(1, uprintf("Lock error !\n"));  
                 return;  
             }  
         }          }
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
   
     return;      return;
 }  }
   
 static inline void  static inline void
 deverrouillage_gestionnaire_signaux()  deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 {  {
     int         semaphore;      int         semaphore;
   
     sem_t       *sem;  
   
     sigset_t    oldset;  
     sigset_t    set;  
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !      // Il faut respecteur l'atomicité des deux opérations suivantes !
   
     sigfillset(&set);      if (pthread_mutex_lock(&mutex_gestionnaires_signaux_atomique) == -1)
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)  
 #   else  
     while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)  #       ifndef SEMAPHORES_NOMMES
         {          sem_wait(&((*s_etat_processus).semaphore_fork));
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  #       else
             BUG(1, uprintf("Unlock error !\n"));          sem_wait((*s_etat_processus).semaphore_fork);
             return;  #       endif
         }          BUG(1, uprintf("Unlock error !\n"));
           return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
Line 1652  deverrouillage_gestionnaire_signaux() Line 1565  deverrouillage_gestionnaire_signaux()
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)      if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)
 #   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("Unlock error !\n"));          BUG(1, uprintf("Unlock error !\n"));
         return;          return;
     }      }
Line 1665  deverrouillage_gestionnaire_signaux() Line 1582  deverrouillage_gestionnaire_signaux()
     {      {
         if (errno != EINTR)          if (errno != EINTR)
         {          {
             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("Unlock error !\n"));              BUG(1, uprintf("Unlock error !\n"));
             return;              return;
         }          }
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_gestionnaires_signaux_atomique) != 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);  #       ifndef SEMAPHORES_NOMMES
           sem_wait(&((*s_etat_processus).semaphore_fork));
   #       else
           sem_wait((*s_etat_processus).semaphore_fork);
   #       endif
         BUG(1, uprintf("Unlock error !\n"));          BUG(1, uprintf("Unlock error !\n"));
         return;          return;
     }      }
   
     if ((sem = pthread_getspecific(semaphore_fork_processus_courant))  #   ifndef SEMAPHORES_NOMMES
             != NULL)      while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
   #   else
       while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
   #   endif
     {      {
         while(sem_wait(sem) == -1)          if (errno != EINTR)
         {          {
             if (errno != EINTR)              BUG(1, uprintf("Unlock error !\n"));
             {              return;
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
                 BUG(1, uprintf("Unlock error !\n"));  
                 return;  
             }  
         }          }
     }      }
   
     if (semaphore == 1)      if (semaphore == 1)
     {      {
 #       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);  
   
             BUG(1, uprintf("Unlock error !\n"));              BUG(1, uprintf("Unlock error !\n"));
             return;              return;
         }          }
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
   
     return;      return;
 }  }
   
   /*
   ================================================================================
     Fonctions de gestion des signaux dans les threads.
   
     Lorsqu'un processus reçoit un signal, il appelle le gestionnaire de signal
     associé qui ne fait qu'envoyer au travers de write() le signal
     reçus dans un pipe. Un second thread est bloqué sur ce pipe et
     effectue le traitement adéquat pour le signal donné.
   ================================================================================
   */
   
 #define test_signal(signal) \  #define test_signal(signal) \
     if (signal_test == SIGTEST) \      if (signal_test == SIGTEST) { signal_test = signal; return; }
     { signal_test = initialisation_queue_interruptions(signal); return; }  
   
 /*  static int          pipe_signaux;
  * Les interruptions sont mise en mémoire puis traitées depuis  
  * la fonction scrutation_injection() parce que les fonctions pthread*()  
  * ne sont pas 'async signal safe'.  
  *  
  * Les interruptions sont ainsi empilées dans un buffer circulaire puis  
  * traitées au fur et à mesure.  
  */  
   
 static struct  logical1
   lancement_thread_signaux(struct_processus *s_etat_processus)
 {  {
 #   define                  SIGNAL_MAX      32      pthread_attr_t                  attributs;
 #   define                  SIGNAL_BUFFER   1024  
 #   define                  ECRITURE        0  
 #   define                  LECTURE         1  
   
     sig_atomic_t            nombre_interruptions_en_queue;      void                            *argument;
     int                     pointeur[SIGNAL_MAX][2];  
   
     pid_t                   pid[SIGNAL_MAX][SIGNAL_BUFFER];      if (pipe((*s_etat_processus).pipe_signaux) != 0)
 } queue_interruptions;      {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return(d_erreur);
       }
   
 pthread_mutex_t             mutex_signal = PTHREAD_MUTEX_INITIALIZER;      pipe_signaux = (*s_etat_processus).pipe_signaux[1];
   
 static inline int      if (pthread_attr_init(&attributs) != 0)
 initialisation_queue_interruptions(int signal)      {
 {          (*s_etat_processus).erreur_systeme = d_es_processus;
     int         i;          return(d_erreur);
       }
   
     if (signal > SIGNAL_MAX)      if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
     {      {
         return(signal + 1);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return(d_erreur);
     }      }
   
     queue_interruptions.nombre_interruptions_en_queue = 0;      argument = (*s_etat_processus).pipe_signaux;
   
     for(i = 0; i < SIGNAL_MAX; i++)      if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
               thread_signaux, argument) != 0)
     {      {
         queue_interruptions.pointeur[i][ECRITURE] = 0;          (*s_etat_processus).erreur_systeme = d_es_processus;
         queue_interruptions.pointeur[i][LECTURE] = 0;          return(d_erreur);
     }      }
   
     return(signal);      return(d_absence_erreur);
 }  }
   
 void  logical1
 interruption1(SIGHANDLER_ARGS)  arret_thread_signaux(struct_processus *s_etat_processus)
 {  {
     pid_t               pid;      unsigned char       signal;
       ssize_t             n;
   
     test_signal(signal);      signal = (unsigned char ) (rpl_sigmax & 0xFF);
   
 #   ifdef _BROKEN_SIGINFO      do
         if ((signal == SIGINT) || (signal == SIGTERM))      {
         {          n = write((*s_etat_processus).pipe_signaux[1], &signal, sizeof(signal));
             // Si l'interruption provient du clavier, il n'y a pas eu d'appel  
             // à queue_in().  
   
             pid = getpid();          if (n < 0)
         }  
         else  
         {          {
             pid = origine_signal(signal);              return(d_erreur);
         }          }
 #   else      } while(n != 1);
   
     /*      pthread_join((*s_etat_processus).thread_signaux, NULL);
      * 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.  
      */  
   
         if (siginfo != NULL)      close((*s_etat_processus).pipe_signaux[0]);
         {      close((*s_etat_processus).pipe_signaux[1]);
             pid = (*siginfo).si_pid;  
         }  
         else  
         {  
             pid = getpid();  
         }  
 #   endif  
   
     queue_interruptions.pid[signal][queue_interruptions.pointeur      return(d_absence_erreur);
             [signal][ECRITURE]] = pid;  
     queue_interruptions.pointeur[signal][ECRITURE] =  
             (queue_interruptions.pointeur[signal][ECRITURE] + 1)  
             % SIGNAL_BUFFER;  
     queue_interruptions.nombre_interruptions_en_queue++;  
     return;  
 }  }
   
 static void  void *
 corps_interruption1(struct_processus *s_etat_processus, int signal, pid_t pid)  thread_signaux(void *argument)
 {  {
     volatile sig_atomic_t   exclusion = 0;      int                     *pipe;
   
     struct_processus        *s_thread_principal;      sigset_t                masque;
   
     verrouillage_gestionnaire_signaux();      struct pollfd           fds;
   
     switch(signal)      unsigned char           signal;
     {  
         case SIGALRM :  
         {  
             if (pid == getpid())  
             {  
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
                 {  
                     printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())      pipe = (int *) argument;
                 {      fds.fd = pipe[0];
                     kill((*s_etat_processus).pid_processus_pere, signal);      fds.events = POLLIN;
                 }      fds.revents = 0;
                 else  
                 {  
                     (*s_etat_processus).var_volatile_alarme = -1;  
                     (*s_etat_processus).var_volatile_requete_arret = -1;  
                 }  
             }  
             else  
             {  
                 if ((s_thread_principal = recherche_thread_principal(getpid()))  
                         != NULL)  
                 {  
                     while((*s_etat_processus).signal_a_traiter == d_vrai);  
                     (*s_etat_processus).signal = signal;  
                     (*s_etat_processus).origine_signal = getpid();  
                     (*s_etat_processus).signal_a_traiter = d_vrai;  
                 }  
             }  
   
             break;      sigfillset(&masque);
         }      pthread_sigmask(SIG_BLOCK, &masque, NULL);
   
         case SIGINT :      do
         case SIGTERM :      {
           if (poll(&fds, 1, -1) == -1)
         {          {
             if (pid == getpid())              pthread_exit(NULL);
             {          }
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
                 {  
                     if (signal == SIGINT)  
                     {  
                         printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),  
                                 (unsigned long long) pthread_self());  
                     }  
                     else  
                     {  
                         printf("[%d] SIGTERM (thread %llu)\n", (int) getpid(),  
                                 (unsigned long long) pthread_self());  
                     }  
   
                     fflush(stdout);          read(fds.fd, &signal, 1);
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())          if (signal != (0xFF & rpl_sigmax))
                 {          {
                     kill((*s_etat_processus).pid_processus_pere, signal);              envoi_signal_processus(getpid(), signal);
                 }              // Un signal SIGALRM est envoyé par le thread de surveillance
                 else              // des signaux jusqu'à ce que les signaux soient tous traités.
                 {          }
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;      } while(signal != (0xFF & rpl_sigmax));
   
                     while(exclusion == 1);      pthread_exit(NULL);
                     exclusion = 1;  }
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)  // Récupération des signaux
                     {  // - SIGINT  (arrêt au clavier)
                         deverrouillage_gestionnaire_signaux();  // - SIGTERM (signal d'arrêt en provenance du système)
                         exclusion = 0;  
                         return;  
                     }  
   
                     if (signal == SIGINT)  void
                     {  interruption1(int signal)
                         if (strncmp(getenv("LANG"), "fr", 2) == 0)  {
                         {      unsigned char       signal_tronque;
                             printf("+++Interruption\n");  
                         }  
                         else  
                         {  
                             printf("+++Interrupt\n");  
                         }  
   
                         fflush(stdout);      test_signal(signal);
                     }  
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;      switch(signal)
                     (*s_etat_processus).var_volatile_alarme = -1;      {
           case SIGINT:
               signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
               write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
               break;
   
                     exclusion = 0;          case SIGTERM:
                 }              signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
             }              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             else              break;
             {  
                 if ((s_thread_principal = recherche_thread_principal(getpid()))  
                         != NULL)  
                 {  
                     while((*s_etat_processus).signal_a_traiter == d_vrai);  
                     (*s_etat_processus).signal = signal;  
                     (*s_etat_processus).origine_signal = getpid();  
                     (*s_etat_processus).signal_a_traiter = d_vrai;  
                 }  
             }  
   
           case SIGUSR1:
               signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
               write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             break;              break;
         }  
   
         default :          default:
         {              // SIGALRM
             BUG(1, uprintf("[%d] Unknown signal %d in this context\n",  
                     (int) getpid(), signal));  
             break;              break;
         }  
     }      }
   
     deverrouillage_gestionnaire_signaux();  
     return;      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
 interruption2(SIGHANDLER_ARGS)  interruption2(int signal)
 {  {
     pid_t               pid;      unsigned char       signal_tronque;
   
     test_signal(signal);      test_signal(signal);
   
 #   ifdef _BROKEN_SIGINFO      signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
     pid = origine_signal(signal);      write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 #   else      return;
     if (siginfo != NULL)  }
   
   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";
   
       test_signal(signal);
   
       if (pid_processus_pere == getpid())
     {      {
         pid = (*siginfo).si_pid;          kill(pid_processus_pere, SIGUSR1);
       }
   
       if (signal != SIGUSR2)
       {
           write(STDERR_FILENO, message_1, strlen(message_1));
     }      }
     else      else
     {      {
         pid = getpid();          write(STDERR_FILENO, message_2, strlen(message_2));
     }      }
 #   endif  
   
     queue_interruptions.pid[signal][queue_interruptions.pointeur      _exit(EXIT_FAILURE);
             [signal][ECRITURE]] = pid;  }
     queue_interruptions.pointeur[signal][ECRITURE] =  
             (queue_interruptions.pointeur[signal][ECRITURE] + 1)  // Récupération des signaux
             % SIGNAL_BUFFER;  // - SIGHUP
   
     /*  void
      * Le signal SIGFSTP provient de la mort du processus de contrôle.  interruption4(int signal)
      * 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      unsigned char       signal_tronque;
      * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo  
      * non initialisée (pointeur NULL) issue de TERMIO.      test_signal(signal);
      */  
       signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
     if (siginfo == NULL)      write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     {      return;
         queue_interruptions.pid[SIGHUP][queue_interruptions.pointeur  }
                 [SIGHUP][ECRITURE]] = pid;  
         queue_interruptions.pointeur[SIGHUP][ECRITURE] =  // Récupération des signaux
                 (queue_interruptions.pointeur[SIGHUP][ECRITURE] + 1)  // - SIGPIPE
                 % SIGNAL_BUFFER;  
         queue_interruptions.nombre_interruptions_en_queue += 2;  void
   interruption5(int signal)
   {
       unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
       unsigned char       signal_tronque;
   
       test_signal(signal);
   
       if (pid_processus_pere == getpid())
       {
           signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
           write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     }      }
   
       write(STDERR_FILENO, message, strlen(message));
     return;      return;
 }  }
   
 static void  inline static void
 corps_interruption2(struct_processus *s_etat_processus, int signal, pid_t pid)  signal_alrm(struct_processus *s_etat_processus, pid_t pid)
 {  {
     struct_processus        *s_thread_principal;      struct_processus        *s_thread_principal;
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         /*          // Si pid est égal à getpid(), le signal à traiter est issu
          *  0 => fonctionnement normal          // du même processus que celui qui va le traiter, mais d'un thread
          * -1 => requête          // différent.
          *  1 => requête acceptée en attente de traitement  
          */  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
   
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             kill((*s_etat_processus).pid_processus_pere, signal);              // 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          else
         {          {
             (*s_etat_processus).var_volatile_requete_arret2 = -1;              // 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      else
     {      {
         // Envoi d'un signal au thread maître du groupe.          // Le signal est issu d'un processus différent. On recherche le
           // thread principal pour remonter le signal.
   
         if ((s_thread_principal = recherche_thread_principal(getpid()))          if ((s_thread_principal = recherche_thread_principal(getpid()))
                 != NULL)                  != NULL)
         {          {
             while((*s_etat_processus).signal_a_traiter == d_vrai);              envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
             (*s_etat_processus).signal = signal;  
             (*s_etat_processus).origine_signal = getpid();  
             (*s_etat_processus).signal_a_traiter = d_vrai;  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  inline static void
 interruption3(SIGHANDLER_ARGS)  signal_term(struct_processus *s_etat_processus, pid_t pid)
 {  {
     // Si on passe par ici, c'est qu'il est impossible de récupérer      struct_processus        *s_thread_principal;
     // l'erreur d'accès à la mémoire. On sort donc du programme quitte à      pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
     // ce qu'il reste des processus orphelins.  
   
     unsigned char       message[] = "+++System : Uncaught access violation\n"      verrouillage_gestionnaire_signaux(s_etat_processus);
                                 "+++System : Aborting !\n;  
   
     if (pid_processus_pere == getpid())      if (pid == getpid())
     {      {
         kill(pid_processus_pere, SIGALRM);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     }          {
               printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     write(STDERR_FILENO, message, strlen(message));          if ((*s_etat_processus).pid_processus_pere != getpid())
     _exit(EXIT_FAILURE);          {
 }              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigterm);
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
 void INTERRUPTION3_A_FIXER()              pthread_mutex_lock(&exclusion);
 {  
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;              if ((*s_etat_processus).var_volatile_requete_arret == -1)
               {
                   deverrouillage_gestionnaire_signaux(s_etat_processus);
                   pthread_mutex_unlock(&exclusion);
                   return;
               }
   
     test_signal(signal);              (*s_etat_processus).var_volatile_requete_arret = -1;
     verrouillage_gestionnaire_signaux();              (*s_etat_processus).var_volatile_alarme = -1;
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)              pthread_mutex_unlock(&exclusion);
     {          }
         deverrouillage_gestionnaire_signaux();  
         return;  
     }      }
       else
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
     {      {
         printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(),          if ((s_thread_principal = recherche_thread_principal(getpid()))
                 (unsigned long long) pthread_self());                  != NULL)
         fflush(stdout);          {
               envoi_signal_contexte(s_thread_principal, rpl_sigterm);
           }
     }      }
   
     if ((*s_etat_processus).var_volatile_recursivite == -1)      deverrouillage_gestionnaire_signaux(s_etat_processus);
     {      return;
         // Segfault dans un appel de fonction récursive  }
         deverrouillage_gestionnaire_signaux();  
         longjmp(contexte, -1);  inline static void
     }  signal_int(struct_processus *s_etat_processus, pid_t pid)
     else  {
       struct_processus        *s_thread_principal;
       volatile sig_atomic_t   exclusion = 0;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
     {      {
         // Segfault dans une routine interne          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         if (strncmp(getenv("LANG"), "fr", 2) == 0)  
         {          {
             printf("+++Système : Violation d'accès\n");              printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
         else  
           if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             printf("+++System : Access violation\n");              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigint);
         }          }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
         fflush(stdout);              while(exclusion == 1);
               exclusion = 1;
         (*s_etat_processus).compteur_violation_d_acces++;  
   
         if ((*s_etat_processus).compteur_violation_d_acces > 1)              if ((*s_etat_processus).var_volatile_requete_arret == -1)
         {              {
             // On vient de récupérer plus d'une erreur de segmentation                  deverrouillage_gestionnaire_signaux(s_etat_processus);
             // dans le même processus ou le même thread. L'erreur n'est pas                  exclusion = 0;
             // récupérable et on sort autoritairement du programme. Il peut                  return;
             // rester des processus orphelins en attente !              }
   
             if (strncmp(getenv("LANG"), "fr", 2) == 0)              if ((*s_etat_processus).langue == 'F')
             {              {
                 printf("+++Système : Violation d'accès, tentative de "                  printf("+++Interruption\n");
                         "terminaison de la tâche\n");  
                 printf("             (defauts multiples)\n");  
             }              }
             else              else
             {              {
                 printf("+++System : Access violation, trying to kill task "                  printf("+++Interrupt\n");
                         "(multiple defaults)\n");  
             }              }
   
             fflush(stdout);              fflush(stdout);
   
             deverrouillage_gestionnaire_signaux();              (*s_etat_processus).var_volatile_requete_arret = -1;
             exit(EXIT_FAILURE);              (*s_etat_processus).var_volatile_alarme = -1;
   
               exclusion = 0;
         }          }
         else      }
       else
       {
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             // Première erreur de segmentation. On essaie de terminer              envoi_signal_contexte(s_thread_principal, rpl_sigint);
             // proprement le thread ou le processus. Le signal ne peut être          }
             // envoyé que depuis le même processus.      }
   
             if (recherche_thread_principal(getpid(), &thread) == d_vrai)      deverrouillage_gestionnaire_signaux(s_etat_processus);
             {      return;
                 if (pthread_equal(thread, pthread_self()) != 0)  }
                 {  
                     deverrouillage_gestionnaire_signaux();  
   
                     if ((*s_etat_processus).pid_processus_pere != getpid())  static inline void
                     {  signal_tstp(struct_processus *s_etat_processus, pid_t pid)
                         // On est dans le thread principal d'un processus.  {
       struct_processus        *s_thread_principal;
   
                         longjmp(contexte_processus, -1);      verrouillage_gestionnaire_signaux(s_etat_processus);
                     }  
                     else  
                     {  
                         // On est dans le thread principal du processus  
                         // père.  
   
                         longjmp(contexte_initial, -1);      if (pid == getpid())
                     }      {
                 }          /*
                 else           *  0 => fonctionnement normal
                 {           * -1 => requête
                     // On est dans un thread fils d'un thread principal.           *  1 => requête acceptée en attente de traitement
            */
   
                     deverrouillage_gestionnaire_signaux();          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
                     longjmp(contexte_thread, -1);          {
                 }              printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
             }                      (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
             // Là, on ramasse les miettes puisque le thread n'existe plus          if ((*s_etat_processus).var_volatile_processus_pere == 0)
             // dans la base (corruption de la mémoire).          {
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigtstp);
           }
           else
           {
               (*s_etat_processus).var_volatile_requete_arret2 = -1;
           }
       }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
             deverrouillage_gestionnaire_signaux();          if ((s_thread_principal = recherche_thread_principal(getpid()))
             longjmp(contexte_initial, -1);                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   static void
   sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
   {
       switch((*((volatile int *) arg1)))
       {
           case 1:
               longjmp(contexte_ecriture, -1);
               break;
   
           case 2:
               longjmp(contexte_impression, -1);
               break;
       }
   
     return;      return;
 }  }
   
 void  void
 interruption4(SIGHANDLER_ARGS)  interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
 {  {
     struct_processus        *s_etat_processus;      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.
   
     test_signal(signal);          sigsegv_leave_handler(sortie_interruption_depassement_pile,
     verrouillage_gestionnaire_signaux();                  (void *) &routine_recursive, NULL, NULL);
       }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      // 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 ((gravite == 0) && (routine_recursive != 0))
     {      {
         deverrouillage_gestionnaire_signaux();          // Il peut s'agir d'un dépassement de pile.
         return;  
           sigsegv_leave_handler(sortie_interruption_depassement_pile,
                   (void *) &routine_recursive, NULL, NULL);
     }      }
   
     /*      // On est dans une bonne vieille violation d'accès. On essaie
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)      // de fermer au mieux l'application.
      */  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      compteur_erreur++;
   
       if (compteur_erreur >= 2)
     {      {
         printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),          // Erreurs multiples, on arrête l'application.
                 (unsigned long long) pthread_self());          interruption3(SIGSEGV);
         fflush(stdout);          return(0);
     }      }
   
     deverrouillage_gestionnaire_signaux();      write(STDERR_FILENO, message, strlen(message));
     return;  
       if (pid_processus_pere == getpid())
       {
           longjmp(contexte_initial, -1);
           return(1);
       }
       else
       {
           longjmp(contexte_processus, -1);
           return(1);
       }
   
       // On renvoie 0 parce qu'on décline toute responsabilité quant à la
       // suite des événements...
       return(0);
 }  }
   
 void  // Traitement de rpl_sigstart
 interruption5(SIGHANDLER_ARGS)  
   static inline void
   signal_start(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t                   pid;      struct_processus        *s_thread_principal;
   
     pthread_t               thread;      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     struct_processus        *s_etat_processus;      if (pid == getpid())
       {
           (*s_etat_processus).demarrage_fils = d_vrai;
       }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
     test_signal(signal);          if ((s_thread_principal = recherche_thread_principal(getpid()))
     verrouillage_gestionnaire_signaux();                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigstart);
           }
       }
   
 #   ifdef _BROKEN_SIGINFO      deverrouillage_gestionnaire_signaux(s_etat_processus);
     pid = origine_signal(signal);      return;
 #   else  }
     pid = (*siginfo).si_pid;  
 #   endif  // 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())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          (*s_etat_processus).redemarrage_processus = d_vrai;
                 == NULL)      }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             deverrouillage_gestionnaire_signaux();              envoi_signal_contexte(s_thread_principal, rpl_sigcont);
             return;  
         }          }
       }
   
       deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
   // Traitement de rpl_sigstop
   
   static inline void
   signal_stop(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
       {
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
Line 2256  interruption5(SIGHANDLER_ARGS) Line 2262  interruption5(SIGHANDLER_ARGS)
     }      }
     else      else
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, signal);              envoi_signal_contexte(s_thread_principal, rpl_sigstop);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  // Traitement de rpl_siginject
 interruption6(SIGHANDLER_ARGS)  
 {  
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  static inline void
     verrouillage_gestionnaire_signaux();  signal_inject(struct_processus *s_etat_processus, pid_t pid)
   
     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] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }  
   
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 void  
 interruption7(SIGHANDLER_ARGS)  
 {  {
     struct_processus        *s_etat_processus;      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     test_signal(signal);  
     verrouillage_gestionnaire_signaux();  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          deverrouillage_gestionnaire_signaux(s_etat_processus);
         return;          return;
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
                 (unsigned long long) pthread_self());                  (unsigned long long) pthread_self());
         fflush(stdout);          fflush(stdout);
     }      }
   
     (*s_etat_processus).var_volatile_requete_arret = -1;      deverrouillage_gestionnaire_signaux(s_etat_processus);
     deverrouillage_gestionnaire_signaux();  
   
     BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));  
     return;      return;
 }  }
   
 void  
 interruption8(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  static inline void
     verrouillage_gestionnaire_signaux();  signal_urg(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
 #   ifdef _BROKEN_SIGINFO      verrouillage_gestionnaire_signaux(s_etat_processus);
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
Line 2371  interruption8(SIGHANDLER_ARGS) Line 2323  interruption8(SIGHANDLER_ARGS)
     {      {
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, SIGURG);              envoi_signal_contexte(s_thread_principal, rpl_sigurg);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigabort
 interruption9(SIGHANDLER_ARGS)  
   static inline void
   signal_abort(struct_processus *s_etat_processus, pid_t pid)
 {  {
     struct_processus        *s_etat_processus;      struct_processus        *s_thread_principal;
   
     test_signal(signal);      verrouillage_gestionnaire_signaux(s_etat_processus);
     verrouillage_gestionnaire_signaux();  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          deverrouillage_gestionnaire_signaux(s_etat_processus);
         return;          return;
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
                 (unsigned long long) pthread_self());                  (unsigned long long) pthread_self());
         fflush(stdout);          fflush(stdout);
     }      }
   
 #   ifdef _BROKEN_SIGINFO      if (pid == getpid())
     if (queue_in(getpid(), signal) != 0)  
     {      {
         return;          (*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)
            */
   
           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
       {
           (*s_etat_processus).arret_depuis_abort = -1;
   
     deverrouillage_gestionnaire_signaux();          // Envoi d'un signal au thread maître du groupe.
     interruption11(signal);  
 #   else          if ((s_thread_principal = recherche_thread_principal(getpid()))
     deverrouillage_gestionnaire_signaux();                  != NULL)
     interruption11(signal, siginfo, context);          {
 #   endif              envoi_signal_contexte(s_thread_principal, rpl_sigabort);
           }
       }
   
       deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  
 interruption10(SIGHANDLER_ARGS)  static inline void
   signal_hup(struct_processus *s_etat_processus, pid_t pid)
 {  {
     file                    *fichier;      file                    *fichier;
   
     struct_processus        *s_etat_processus;  
   
     unsigned char           nom[8 + 64 + 1];      unsigned char           nom[8 + 64 + 1];
   
     test_signal(signal);      verrouillage_gestionnaire_signaux(s_etat_processus);
     verrouillage_gestionnaire_signaux();  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          deverrouillage_gestionnaire_signaux(s_etat_processus);
         return;          return;
     }      }
   
Line 2452  interruption10(SIGHANDLER_ARGS) Line 2424  interruption10(SIGHANDLER_ARGS)
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
                 (unsigned long long) pthread_self());                  (unsigned long long) pthread_self());
         fflush(stdout);          fflush(stdout);
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  void
 interruption11(SIGHANDLER_ARGS)  traitement_exceptions_gsl(const char *reason, const char *file,
           int line, int gsl_errno)
 {  {
     pid_t                   pid;      code_erreur_gsl = gsl_errno;
       envoi_signal_processus(getpid(), rpl_sigexcept);
       return;
   }
   
     pthread_t               thread;  static inline void
   signal_except(struct_processus *s_etat_processus, pid_t pid)
   {
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
       {
           deverrouillage_gestionnaire_signaux(s_etat_processus);
           return;
       }
   
     struct_processus        *s_etat_processus;      (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
       deverrouillage_gestionnaire_signaux(s_etat_processus);
   
     test_signal(signal);      return;
     verrouillage_gestionnaire_signaux();  }
   
   static inline void
   envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
           pid_t pid_source)
   {
       switch(signal)
       {
           case rpl_signull:
               break;
   
           case rpl_sigint:
               signal_int(s_etat_processus, pid_source);
               break;
   
           case rpl_sigterm:
               signal_term(s_etat_processus, pid_source);
               break;
   
           case rpl_sigstart:
               signal_start(s_etat_processus, pid_source);
               break;
   
           case rpl_sigcont:
               signal_cont(s_etat_processus, pid_source);
               break;
   
           case rpl_sigstop:
               signal_stop(s_etat_processus, pid_source);
               break;
   
           case rpl_sigabort:
               signal_abort(s_etat_processus, pid_source);
               break;
   
           case rpl_sigurg:
               signal_urg(s_etat_processus, pid_source);
               break;
   
           case rpl_siginject:
               signal_inject(s_etat_processus, pid_source);
               break;
   
           case rpl_sigalrm:
               signal_alrm(s_etat_processus, pid_source);
               break;
   
           case rpl_sighup:
               signal_hup(s_etat_processus, pid_source);
               break;
   
           case rpl_sigtstp:
               signal_tstp(s_etat_processus, pid_source);
               break;
   
           case rpl_sigexcept:
               signal_except(s_etat_processus, pid_source);
               break;
   
           default:
               if ((*s_etat_processus).langue == 'F')
               {
                   printf("+++System : Signal inconnu (%d) !\n", signal);
               }
               else
               {
                   printf("+++System : Spurious signal (%d) !\n", signal);
               }
   
               break;
       }
   
       return;
   }
   
   void
   scrutation_interruptions(struct_processus *s_etat_processus)
   {
       // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
   
       // Les pointeurs de lecture pointent sur les prochains éléments
       // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
       // écrire.
   
 #   ifdef _BROKEN_SIGINFO  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     pid = origine_signal(signal);          if (sem_trywait(&((*s_queue_signaux).semaphore)) == 0)
 #   else  #   else
     pid = (*siginfo).si_pid;          if (sem_trywait(semaphore_queue_signaux) == 0)
 #   endif  #   endif
   
     if (pid == getpid())  
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          while((*s_queue_signaux).pointeur_lecture !=
                 == NULL)                  (*s_queue_signaux).pointeur_ecriture)
         {          {
             deverrouillage_gestionnaire_signaux();              // Il y a un signal en attente dans le segment partagé. On le
             return;              // 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;
                   }
               }
         }          }
   
         (*s_etat_processus).arret_depuis_abort = -1;  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_post(&((*s_queue_signaux).semaphore));
   #       else
               sem_post(semaphore_queue_signaux);
   #       endif
       }
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      // Interruptions qui arrivent depuis le groupe courant de threads.
   
       if (pthread_mutex_trylock(&mutex_interruptions) == 0)
       {
           while((*s_etat_processus).pointeur_signal_lecture !=
                   (*s_etat_processus).pointeur_signal_ecriture)
         {          {
             printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(),              // Il y a un signal dans la queue du thread courant. On le traite.
                     (unsigned long long) pthread_self());  
             fflush(stdout);              envoi_interruptions(s_etat_processus,
                       (*s_etat_processus).signaux_en_queue
                       [(*s_etat_processus).pointeur_signal_lecture],
                       getpid());
               (*s_etat_processus).pointeur_signal_lecture =
                       ((*s_etat_processus).pointeur_signal_lecture + 1)
                       % LONGUEUR_QUEUE_SIGNAUX;
   
   #           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_mutex_unlock(&mutex_interruptions);
          * 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)      return;
   }
   
   /*
   ================================================================================
     Fonction renvoyant le nom du segment de mémoire partagée en fonction
     du pid du processus.
   ================================================================================
     Entrée : Chemin absolue servant de racine, pid du processus
   --------------------------------------------------------------------------------
     Sortie : NULL ou nom du segment
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   static unsigned char *
   nom_segment(unsigned char *chemin, pid_t pid)
   {
       unsigned char               *fichier;
   
   #   ifdef IPCS_SYSV // !POSIX
   #       ifndef OS2 // !OS2
   
               if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *
                       sizeof(unsigned char))) == NULL)
               {
                   return(NULL);
               }
   
               sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
   #       else // OS2
               if ((fichier = malloc((10 + 256 + 1) * sizeof(unsigned char)))
                       == NULL)
               {
                   return(NULL);
               }
   
               sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
   #       endif // OS2
   #   else // POSIX
   
           if ((fichier = malloc((1 + 256 + 1) *
                   sizeof(unsigned char))) == NULL)
         {          {
             (*s_etat_processus).var_volatile_requete_arret = -1;              return(NULL);
         }          }
         else  
           sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
   #   endif
   
       return(fichier);
   }
   
   
   /*
   ================================================================================
     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)
   {
   #   ifndef OS2
           int                         segment;
   #   endif
   
   #   ifndef IPCS_SYSV
   #       ifdef SEMAPHORES_NOMMES
               sem_t                   *semaphore;
               sem_t                   *signalisation;
   #       endif
   #   else
   #       ifndef OS2
               int                     desc;
               key_t                   clef;
   #       endif
   #   endif
   
       struct_queue_signaux            *queue;
   
       unsigned char                   *nom;
   
       // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
       // mémoire puis d'y inscrire le signal à traiter.
   
       if (pid == getpid())
       {
           // Le signal est envoyé au même processus.
   
           if (s_queue_signaux == NULL)
         {          {
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;              return(1);
         }          }
     }  
     else  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     {              while(sem_wait(&((*s_queue_signaux).semaphore)) != 0)
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  #       else
                 == NULL)              while(sem_wait(semaphore_queue_signaux) != 0)
   #       endif
         {          {
             deverrouillage_gestionnaire_signaux();              if (errno != EINTR)
             return;              {
                   return(1);
               }
         }          }
   
         (*s_etat_processus).arret_depuis_abort = -1;          (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .pid = pid;
           (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .signal = signal;
   
         // Envoi d'un signal au thread maître du groupe.          (*s_queue_signaux).pointeur_ecriture =
                   ((*s_queue_signaux).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               if (sem_post(&((*s_queue_signaux).semaphore)) != 0)
   #       else
               if (sem_post(semaphore_queue_signaux) != 0)
   #       endif
         {          {
             pthread_kill(thread, signal);              return(1);
             deverrouillage_gestionnaire_signaux();          }
             return;  
   #       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
       {
           // Le signal est envoyé depuis un processus distinct.
   
     deverrouillage_gestionnaire_signaux();  #       ifdef IPCS_SYSV
     return;              if ((nom = nom_segment(racine_segment, pid)) == NULL)
               {
                   return(1);
               }
   
   #           ifndef OS2 // SysV
                   if ((desc = open(nom, O_RDWR)) == -1)
                   {
                       free(nom);
                       return(1);
                   }
   
                   close(desc);
   
                   if ((clef = ftok(nom, 1)) == -1)
                   {
                       free(nom);
                       return(1);
                   }
   
                   free(nom);
   
                   if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
                           == -1)
                   {
                       return(1);
                   }
   
                   queue = shmat(segment, NULL, 0);
   #           else // OS/2
                   if (DosGetNamedSharedMem((PVOID) &queue, nom,
                           PAG_WRITE | PAG_READ) != 0)
                   {
                       free(nom);
                       return(1);
                   }
   
                   free(nom);
   #           endif
   #       else // POSIX
               if ((nom = nom_segment(racine_segment, pid)) == NULL)
               {
                   return(1);
               }
   
               if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
               {
                   free(nom);
                   return(1);
               }
   
               free(nom);
   
               if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
                       PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
                       MAP_FAILED)
               {
                   close(segment);
                   return(1);
               }
   #       endif
   
               // À ce moment, le segment de mémoire partagée est projeté
               // dans l'espace du processus.
   
   #       ifndef IPCS_SYSV // POSIX
   #           ifndef SEMAPHORES_NOMMES
                   while(sem_wait(&((*queue).semaphore)) != 0)
                   {
                       if (errno != EINTR)
                       {
                           return(1);
                       }
                   }
   #           else
                   if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
                   {
                       return(1);
                   }
   
                   if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
                           == SEM_FAILED)
                   {
                       return(1);
                   }
   
                   while(sem_wait(semaphore) != 0)
                   {
                       if (errno != EINTR)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           return(1);
                       }
                   }
   #           endif
   #       else // IPCS_SYSV
               while(sem_wait(&((*queue).semaphore)) != 0)
               {
                   if (errno != EINTR)
                   {
                       return(1);
                   }
               }
   #       endif
   
           (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
           (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
   
           (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
   #       ifndef IPCS_SYSV // POSIX
   #           ifndef SEMAPHORES_NOMMES
                   if (sem_post(&((*queue).semaphore)) != 0)
                   {
                       return(1);
                   }
   
                   if (sem_post(&((*queue).signalisation)) != 0)
                   {
                       return(1);
                   }
   #           else
                   if (sem_post(semaphore) != 0)
                   {
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (sem_close(semaphore) != 0)
                   {
                       return(1);
                   }
   
                   if (sem_post(signalisation) != 0)
                   {
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (sem_close(signalisation) != 0)
                   {
                       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);
               }
   
               if (sem_post(&((*queue).signalisation)) != 0)
               {
                   return(1);
               }
   
   #           ifndef OS2 // SysV
                   if (shmdt(queue) != 0)
                   {
                       return(1);
                   }
   #           else // OS/2
                   // Pendant de DosGetNamedSHaredMem()
   #           endif
   #       endif
       }
   
       return(0);
 }  }
   
 void  int
 traitement_exceptions_gsl(const char *reason, const char *file,  envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
         int line, int gsl_errno)  
 {  {
     struct_processus        *s_etat_processus;      // Un signal est envoyé d'un thread à un autre thread du même processus.
   
     verrouillage_gestionnaire_signaux();      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      struct_processus                        *s_etat_processus;
   
       if (pthread_mutex_lock(&mutex_liste_threads) != 0)
     {      {
         deverrouillage_gestionnaire_signaux();          return(1);
         return;  
     }      }
   
     (*s_etat_processus).var_volatile_exception_gsl = gsl_errno;      l_element_courant = liste_threads;
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 static inline void      while(l_element_courant != NULL)
 structation_interruptions_elementaires(struct_processus *s_etat_processus,  
         int signal, pid_t pid)  
 {  
     switch(signal)  
     {      {
         case SIGINT:          if (((*((struct_thread *) (*l_element_courant).donnee)).pid
         case SIGTERM:                  == getpid()) && (pthread_equal((*((struct_thread *)
         case SIGALRM:                  (*l_element_courant).donnee)).tid, tid) != 0))
         {          {
             corps_interruption1(s_etat_processus, signal, pid);  
             break;              break;
         }          }
   
         case SIGTSTP:          l_element_courant = (*l_element_courant).suivant;
         {  
             corps_interruption2(s_etat_processus, signal, pid);  
         }  
     }      }
   
     return;      if (l_element_courant == NULL)
       {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
       if (pthread_mutex_lock(&mutex_interruptions) != 0)
       {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
       s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
               .s_etat_processus;
   
       (*s_etat_processus).signaux_en_queue
               [(*s_etat_processus).pointeur_signal_ecriture] = signal;
       (*s_etat_processus).pointeur_signal_ecriture =
               ((*s_etat_processus).pointeur_signal_ecriture + 1)
               % LONGUEUR_QUEUE_SIGNAUX;
   
       if (pthread_mutex_unlock(&mutex_interruptions) != 0)
       {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
       if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
       {
           return(1);
       }
   
   #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
       {
           return(1);
       }
   #   else
       if (sem_post(semaphore_signalisation) != 0)
       {
           return(1);
       }
   #   endif
   
       return(0);
   }
   
   int
   envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
           enum signaux_rpl signal)
   {
       pthread_mutex_lock(&mutex_interruptions);
       (*s_etat_processus_a_signaler).signaux_en_queue
               [(*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(&mutex_interruptions);
   
   #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
       {
           return(1);
       }
   #   else
       if (sem_post(semaphore_signalisation) != 0)
       {
           return(1);
       }
   #   endif
   
       return(0);
 }  }
   
   
   /*
   ================================================================================
     Fonction créant un segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
 void  void
 scrutation_interruptions(struct_processus *s_etat_processus)  creation_queue_signaux(struct_processus *s_etat_processus)
 {  {
     int             i;      pthread_attr_t                  attributs;
   
     // Interruption par processus.      unsigned char                   *nom;
   
     if (pthread_mutex_lock(&mutex_signal) != 0)      racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
   
   #   ifndef IPCS_SYSV // POSIX
           if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
                   getpid())) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
                   S_IRUSR | S_IWUSR)) == -1)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
                   PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
   
           if (((void *) s_queue_signaux) == ((void *) -1))
           {
               if (shm_unlink(nom) == -1)
               {
                   free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           free(nom);
   
   #       ifndef SEMAPHORES_NOMMES
               sem_init(&((*s_queue_signaux).semaphore), 1, 1);
               sem_init(&((*s_queue_signaux).signalisation), 1, 0);
   #       else
               if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
                       == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               if ((semaphore_signalisation = sem_init2(1, getpid(),
                       SEM_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   #       endif
   
           (*s_queue_signaux).pointeur_lecture = 0;
           (*s_queue_signaux).pointeur_ecriture = 0;
           (*s_queue_signaux).requete_arret = d_faux;
   
           if (msync(s_queue_signaux, sizeof(struct_queue_signaux), 0))
           {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   #   else // IPCS_SYSV
   #       ifndef OS2
               int                             segment;
               int                             support;
   
               key_t                           clef;
   
               // Création d'un segment de données associé au PID du processus
               // courant
   
               if ((nom = nom_segment((*s_etat_processus)
                       .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               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;
               }
   
               if ((clef = ftok(nom, 1)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               close(support);
               free(nom);
   
               if ((segment = shmget(clef, sizeof(struct_queue_signaux),
                       IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               s_queue_signaux = shmat(segment, NULL, 0);
               f_queue_signaux = segment;
   
               if (((void *) s_queue_signaux) == ((void *) -1))
               {
                   if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return;
                   }
   
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               sem_init(&((*s_queue_signaux).semaphore), 1, 1);
               sem_init(&((*s_queue_signaux).signalisation), 1, 0);
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       else // OS/2
               if ((nom = nom_segment(NULL, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
                       sizeof(struct_queue_signaux),
                       PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
               {
                   free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               free(nom);
   
               sem_init(&((*s_queue_signaux).semaphore), 1, 1);
               sem_init(&((*s_queue_signaux).signalisation), 1, 0);
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       endif
   #   endif
   
       // Lancement du thread de récupération des signaux.
   
       if (pthread_attr_init(&attributs) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     if (queue_interruptions.nombre_interruptions_en_queue > 0)      if (pthread_attr_setdetachstate(&attributs,
               PTHREAD_CREATE_JOINABLE) != 0)
     {      {
         for(i = 0; i < SIGNAL_MAX; i++)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             if ((queue_interruptions.pointeur[i][ECRITURE] -      }
                     queue_interruptions.pointeur[i][LECTURE]) != 0)  
             {  
                 // Il y a une interruption dans la queue.  
   
                 queue_interruptions.nombre_interruptions_en_queue--;  #   ifdef SCHED_OTHER
                 scrutation_interruptions_elementaires(s_etat_processus, i,      if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0)
                         queue_interruptions.pid[signal]      {
                         [queue_interruptions.pointeur[signal][LECTURE]]);          (*s_etat_processus).erreur_systeme = d_es_processus;
                 queue_interruptions.pointeur[signal][LECTURE] =          return;
                         (queue_interruptions.pointeur[signal][LECTURE] + 1)  
                         % SIGNAL_BUFFER;  
             }  
         }  
     }      }
   #   endif
   
     if (pthread_mutex_unlock(&mutex_signal) != 0)  #   ifdef PTHREAD_EXPLICIT_SCHED
       if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   #   endif
   
     // Interruption par thread  #   ifdef PTHREAD_SCOPE_SYSTEM
       if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   #   endif
   
     if ((*s_etat_processus).signal_a_traiter == d_vrai)      if (pthread_attr_destroy(&attributs) != 0)
     {      {
         (*s_etat_processus).signal_a_traiter = d_faux;          (*s_etat_processus).erreur_systeme = d_es_processus;
         scrutation_interruptions_elementaires(s_etat_processus,          return;
                 (*s_etat_processus).signal, (*s_etat_processus).origine_signal);  
     }      }
   
       if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
               thread_surveillance_signaux, s_etat_processus) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
       return;
   }
   
   
   /*
   ================================================================================
     Fonction libérant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   void
   liberation_queue_signaux(struct_processus *s_etat_processus)
   {
       // Incrémenter le sémaphore pour être sûr de le débloquer.
   
       (*s_queue_signaux).requete_arret = d_vrai;
   
   #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       sem_post(&((*s_queue_signaux).signalisation));
   #   else
       sem_post(semaphore_signalisation);
   #   endif
   
       pthread_join((*s_queue_signaux).thread_signaux, NULL);
   
   #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
               if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       else // OS/2
   #       endif
   #   else // POSIX
   #       ifndef SEMAPHORES_NOMMES
               sem_close(&((*s_queue_signaux).semaphore));
               sem_close(&((*s_queue_signaux).signalisation));
   #       else
               sem_close(semaphore_queue_signaux);
               sem_close(semaphore_signalisation);
   #       endif
   
           if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           close(f_queue_signaux);
   #   endif
   
       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
   destruction_queue_signaux(struct_processus *s_etat_processus)
   {
   #   ifndef OS2
           unsigned char       *nom;
   #   endif
   
       // Incrémenter le sémaphore pour être sûr de le débloquer.
   
       (*s_queue_signaux).requete_arret = d_vrai;
   
   #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       sem_post(&((*s_queue_signaux).signalisation));
   #   else
       sem_post(semaphore_signalisation);
   #   endif
   
       pthread_join((*s_queue_signaux).thread_signaux, NULL);
   
   #   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)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               unlink((*s_queue_signaux).semaphore.path);
               free((*s_queue_signaux).semaphore.path);
   
               if (semctl((*s_queue_signaux).signalisation.sem, 0, IPC_RMID) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               unlink((*s_queue_signaux).signalisation.path);
               free((*s_queue_signaux).signalisation.path);
   
               if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if ((nom = nom_segment((*s_etat_processus)
                       .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               unlink(nom);
               free(nom);
   #       else
               sem_close(&((*s_queue_signaux).semaphore));
               sem_destroy(&((*s_queue_signaux).semaphore));
   
               sem_close(&((*s_queue_signaux).signalisation));
               sem_destroy(&((*s_queue_signaux).signalisation));
   
               if (DosFreeMem(s_queue_signaux) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       endif
   #   else // POSIX
   #       ifndef SEMAPHORES_NOMMES
               sem_close(&((*s_queue_signaux).semaphore));
               sem_destroy(&((*s_queue_signaux).semaphore));
   
               sem_close(&((*s_queue_signaux).signalisation));
               sem_destroy(&((*s_queue_signaux).signalisation));
   #       else
               sem_close(semaphore_queue_signaux);
               sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
   
               sem_close(semaphore_signalisation);
               sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
   #       endif
   
           if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           if ((nom = nom_segment(NULL, getpid())) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           close(f_queue_signaux);
   
           if (shm_unlink(nom) != 0)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           free(nom);
   #   endif
   
     return;      return;
 }  }
   

Removed from v.1.66  
changed lines
  Added in v.1.121


CVSweb interface <joel.bertrand@systella.fr>