Diff for /rpl/src/interruptions.c between versions 1.33 and 1.112

version 1.33, 2010/08/22 16:38:36 version 1.112, 2012/12/18 13:19:39
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.18    RPL/2 (R) version 4.1.12
   Copyright (C) 1989-2010 Dr. BERTRAND Joël    Copyright (C) 1989-2012 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;
   
       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 ((*s_queue_signaux).requete_arret == d_vrai)
               {
                   break;
               }
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_post(&(*s_queue_signaux).signalisation);
   #           else
               sem_post(semaphore_signalisation);
   #           endif
   
               nombre_signaux_envoyes = 0;
               sched_yield();
   
               // Dans un premier temps, on verrouille la queue des signaux
               // affectée au processus courant pour vérifier s'il y a quelque
               // chose à traiter.
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_wait(&(*s_queue_signaux).semaphore);
   #           else
               sem_wait(semaphore_queue_signaux);
   #           endif
   
               if ((*s_queue_signaux).pointeur_lecture !=
                       (*s_queue_signaux).pointeur_ecriture)
               {
                   // Attention : raise() envoit le signal au thread appelant !
                   // kill() l'envoie au processus appelant, donc dans notre
                   // cas à un thread aléatoire du processus, ce qui nous
                   // convient tout à fait puisqu'il s'agit de débloquer les
                   // appels système lents.
   
                   nombre_signaux_envoyes++;
                   kill(getpid(), SIGALRM);
               }
   
   #           if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               sem_post(&(*s_queue_signaux).semaphore);
   #           else
               sem_post(semaphore_queue_signaux);
   #           endif
   
               // Dans un second temps, on balaye toutes les queues de signaux
               // des threads du processus courant.
   
               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 199  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 221  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 243  void
 insertion_thread_surveillance(struct_processus *s_etat_processus,  insertion_thread_surveillance(struct_processus *s_etat_processus,
         struct_descripteur_thread *s_argument_thread)          struct_descripteur_thread *s_argument_thread)
 {  {
     sigset_t                                    oldset;  
     sigset_t                                    set;  
   
     volatile struct_liste_chainee_volatile      *l_nouvel_objet;      volatile struct_liste_chainee_volatile      *l_nouvel_objet;
   
     sigfillset(&set);  
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
     if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))      if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
             == NULL)              == NULL)
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_lock(&mutex_liste_threads) != 0)
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     pthread_mutex_lock(&((*s_argument_thread).mutex));      pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references));
     (*s_argument_thread).nombre_references++;      (*s_argument_thread).nombre_references++;
     pthread_mutex_unlock(&((*s_argument_thread).mutex));      pthread_mutex_unlock(&((*s_argument_thread).mutex_nombre_references));
   
     (*l_nouvel_objet).suivant = liste_threads_surveillance;      (*l_nouvel_objet).suivant = liste_threads_surveillance;
     (*l_nouvel_objet).donnee = (void *) s_argument_thread;      (*l_nouvel_objet).donnee = (void *) s_argument_thread;
   
     liste_threads_surveillance = l_nouvel_objet;      liste_threads_surveillance = l_nouvel_objet;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
     return;      return;
 }  }
   
 void  void
 retrait_thread(struct_processus *s_etat_processus)  retrait_thread(struct_processus *s_etat_processus)
 {  {
     sigset_t                                oldset;  
     sigset_t                                set;  
   
     volatile struct_liste_chainee_volatile  *l_element_precedent;      volatile struct_liste_chainee_volatile  *l_element_precedent;
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     sigfillset(&set);      if (pthread_mutex_lock(&mutex_liste_threads) != 0)
     pthread_sigmask(SIG_BLOCK, &set, &oldset);  
   
 #   ifndef SEMAPHORES_NOMMES  
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     l_element_precedent = NULL;      l_element_precedent = NULL;
Line 256  retrait_thread(struct_processus *s_etat_ Line 306  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 320  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 363  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 388  retrait_thread_surveillance(struct_proce
   
     if (l_element_courant == NULL)      if (l_element_courant == NULL)
     {      {
 #       ifndef SEMAPHORES_NOMMES          pthread_mutex_unlock(&mutex_liste_threads);
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
Line 378  retrait_thread_surveillance(struct_proce Line 402  retrait_thread_surveillance(struct_proce
         (*l_element_precedent).suivant = (*l_element_courant).suivant;          (*l_element_precedent).suivant = (*l_element_courant).suivant;
     }      }
   
     if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)      if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
               != 0)
     {      {
 #       ifndef SEMAPHORES_NOMMES          pthread_mutex_unlock(&mutex_liste_threads);
         sem_post(&semaphore_liste_threads);  
 #       else  
         sem_post(semaphore_liste_threads);  
 #       endif  
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
Line 400  retrait_thread_surveillance(struct_proce Line 418  retrait_thread_surveillance(struct_proce
   
     if ((*s_argument_thread).nombre_references == 0)      if ((*s_argument_thread).nombre_references == 0)
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES              pthread_mutex_unlock(&mutex_liste_threads);
             sem_post(&semaphore_liste_threads);  
 #           else  
             sem_post(semaphore_liste_threads);  
 #           endif  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
   
         pthread_mutex_destroy(&((*s_argument_thread).mutex));          pthread_mutex_destroy(&((*s_argument_thread).mutex));
           pthread_mutex_destroy(&((*s_argument_thread).mutex_nombre_references));
         free(s_argument_thread);          free(s_argument_thread);
     }      }
     else      else
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES              pthread_mutex_unlock(&mutex_liste_threads);
             sem_post(&semaphore_liste_threads);  
 #           else  
             sem_post(semaphore_liste_threads);  
 #           endif  
             pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
             sigpending(&set);  
   
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             return;              return;
         }          }
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
         sigpending(&set);  
   
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     free((struct_liste_chainee_volatile *) l_element_courant);      free((struct_liste_chainee_volatile *) l_element_courant);
   
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);  
     sigpending(&set);  
   
     return;      return;
 }  }
   
Line 460  verrouillage_threads_concurrents(struct_ Line 456  verrouillage_threads_concurrents(struct_
 {  {
     volatile struct_liste_chainee_volatile  *l_element_courant;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_lock(&mutex_liste_threads) != 0)
     while(sem_wait(&semaphore_liste_threads) == -1)  
 #   else  
     while(sem_wait(semaphore_liste_threads) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             (*s_etat_processus).erreur_systeme = d_es_processus;  
             return;  
         }  
     }      }
   
     l_element_courant = liste_threads;      l_element_courant = liste_threads;
Line 482  verrouillage_threads_concurrents(struct_ Line 471  verrouillage_threads_concurrents(struct_
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)                  while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)
                     .donnee)).s_etat_processus).semaphore_fork)) == -1)                          .donnee)).s_etat_processus).semaphore_fork)) == -1)
 #           else  #           else
             while(sem_wait((*(*((struct_thread *) (*l_element_courant)                  while(sem_wait((*(*((struct_thread *) (*l_element_courant)
                     .donnee)).s_etat_processus).semaphore_fork) == -1)                          .donnee)).s_etat_processus).semaphore_fork) == -1)
 #           endif  #           endif
             {              {
                 if (errno != EINTR)                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 {                  return;
                     (*s_etat_processus).erreur_systeme = d_es_processus;  
                     return;  
                 }  
             }              }
         }          }
   
Line 517  deverrouillage_threads_concurrents(struc Line 503  deverrouillage_threads_concurrents(struc
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             if (sem_post(&((*(*((struct_thread *)                  if (sem_post(&((*(*((struct_thread *)
                     (*l_element_courant).donnee)).s_etat_processus)                          (*l_element_courant).donnee)).s_etat_processus)
                     .semaphore_fork)) != 0)                          .semaphore_fork)) != 0)
 #           else  #           else
             if (sem_post((*(*((struct_thread *)                  if (sem_post((*(*((struct_thread *)
                     (*l_element_courant).donnee)).s_etat_processus)                          (*l_element_courant).donnee)).s_etat_processus)
                     .semaphore_fork) != 0)                          .semaphore_fork) != 0)
 #           endif  #           endif
             {              {
 #               ifndef SEMAPHORES_NOMMES                  if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
                 if (sem_post(&semaphore_liste_threads) != 0)  
                 {  
                     (*s_etat_processus).erreur_systeme = d_es_processus;  
                     return;  
                 }  
 #               else  
                 if (sem_post(semaphore_liste_threads) != 0)  
                 {                  {
                     (*s_etat_processus).erreur_systeme = d_es_processus;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     return;                      return;
                 }                  }
 #               endif  
   
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 return;                  return;
Line 548  deverrouillage_threads_concurrents(struc Line 526  deverrouillage_threads_concurrents(struc
         l_element_courant = (*l_element_courant).suivant;          l_element_courant = (*l_element_courant).suivant;
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
     if (sem_post(&semaphore_liste_threads) != 0)  
 #   else  
     if (sem_post(semaphore_liste_threads) != 0)  
 #   endif  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
Line 566  liberation_threads(struct_processus *s_e Line 540  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;
   
       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;
   
     unsigned long                               i;      unsigned long                               i;
   
     void                                        *element_candidat;      void                                        *element_candidat;
Line 582  liberation_threads(struct_processus *s_e Line 559  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 676  liberation_threads(struct_processus *s_e Line 642  liberation_threads(struct_processus *s_e
                 s_argument_thread = (struct_descripteur_thread *)                  s_argument_thread = (struct_descripteur_thread *)
                         (*((struct_liste_chainee *) element_courant)).donnee;                          (*((struct_liste_chainee *) element_courant)).donnee;
   
                 if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)                  if (pthread_mutex_lock(&((*s_argument_thread)
                           .mutex_nombre_references)) != 0)
                 {                  {
                     (*s_etat_processus).erreur_systeme = d_es_processus;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     sem_post(&semaphore_liste_threads);                      pthread_mutex_unlock(&mutex_liste_threads);
                     return;                      return;
                 }                  }
   
Line 700  liberation_threads(struct_processus *s_e Line 667  liberation_threads(struct_processus *s_e
                     close((*s_argument_thread)                      close((*s_argument_thread)
                             .pipe_nombre_interruptions_attente[0]);                              .pipe_nombre_interruptions_attente[0]);
   
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          pthread_mutex_unlock(&mutex_liste_threads);
                         return;                          return;
                     }                      }
   
                     pthread_mutex_destroy(&((*s_argument_thread).mutex));                      pthread_mutex_destroy(&((*s_argument_thread).mutex));
                       pthread_mutex_destroy(&((*s_argument_thread)
                               .mutex_nombre_references));
   
                     if ((*s_argument_thread).processus_detache == d_faux)                      if ((*s_argument_thread).processus_detache == d_faux)
                     {                      {
Line 723  liberation_threads(struct_processus *s_e Line 692  liberation_threads(struct_processus *s_e
                 }                  }
                 else                  else
                 {                  {
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          pthread_mutex_unlock(&mutex_liste_threads);
                         return;                          return;
                     }                      }
                 }                  }
Line 796  liberation_threads(struct_processus *s_e Line 765  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             for(i = 0; i < (*s_etat_processus).nombre_variables; i++)              // ne peut être effacé qu'une seule fois
             {  
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
   
                 // Les variables de niveau 0 sont des définitions qui  
                 // ne sont pas copiées entre threads.  
                 if ((*s_etat_processus).s_liste_variables[i].niveau > 0)  
                 {  
                     liberation(s_etat_processus,  
                             (*s_etat_processus).s_liste_variables[i].objet);  
                 }  
   
                 free((*s_etat_processus).s_liste_variables[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables);  
   
             for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)  
             {  
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
   
                 liberation(s_etat_processus, (*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet);  
                 free((*s_etat_processus).s_liste_variables_statiques[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables_statiques);  
   
             // Ne peut être effacé qu'une seule fois  
             if (suppression_variables_partagees == d_faux)              if (suppression_variables_partagees == d_faux)
             {              {
                 suppression_variables_partagees = d_vrai;                  suppression_variables_partagees = d_vrai;
   
                 for(i = 0; i < (*(*s_etat_processus)                  liberation_arbre_variables_partagees(s_etat_processus,
                         .s_liste_variables_partagees).nombre_variables; i++)                          (*(*s_etat_processus).s_arbre_variables_partagees));
                 {  
                     pthread_mutex_trylock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
                     pthread_mutex_unlock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
   
                     liberation(s_etat_processus, (*(*s_etat_processus)                  l_element_partage_courant = (*(*s_etat_processus)
                             .s_liste_variables_partagees).table[i].objet);                          .l_liste_variables_partagees);
                     free((*(*s_etat_processus).s_liste_variables_partagees)  
                             .table[i].nom);  
                 }  
   
                 if ((*(*s_etat_processus).s_liste_variables_partagees).table                  while(l_element_partage_courant != NULL)
                         != NULL)  
                 {                  {
                     free((struct_variable_partagee *) (*(*s_etat_processus)                      l_element_partage_suivant =
                             .s_liste_variables_partagees).table);                              (*l_element_partage_courant).suivant;
                       free(l_element_partage_courant);
                       l_element_partage_courant = l_element_partage_suivant;
                 }                  }
               }
   
                 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 1321  liberation_threads(struct_processus *s_e Line 1256  liberation_threads(struct_processus *s_e
             liberation_allocateur(s_etat_processus);              liberation_allocateur(s_etat_processus);
   
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             sem_post(&((*s_etat_processus).semaphore_fork));                  sem_post(&((*s_etat_processus).semaphore_fork));
             sem_destroy(&((*s_etat_processus).semaphore_fork));                  sem_destroy(&((*s_etat_processus).semaphore_fork));
 #           else  #           else
             sem_post((*s_etat_processus).semaphore_fork);                  sem_post((*s_etat_processus).semaphore_fork);
             sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork);                  sem_close((*s_etat_processus).semaphore_fork);
 #           endif  #           endif
   
               liberation_contexte_cas(s_etat_processus);
             free(s_etat_processus);              free(s_etat_processus);
   
             s_etat_processus = candidat;              s_etat_processus = candidat;
Line 1350  liberation_threads(struct_processus *s_e Line 1286  liberation_threads(struct_processus *s_e
         s_argument_thread = (struct_descripteur_thread *)          s_argument_thread = (struct_descripteur_thread *)
                 (*l_element_courant).donnee;                  (*l_element_courant).donnee;
   
         if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
                   != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             sem_post(&semaphore_liste_threads);              pthread_mutex_unlock(&mutex_liste_threads);
             return;              return;
         }          }
   
Line 1373  liberation_threads(struct_processus *s_e Line 1310  liberation_threads(struct_processus *s_e
             close((*s_argument_thread).pipe_interruptions[0]);              close((*s_argument_thread).pipe_interruptions[0]);
             close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);              close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);
   
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  pthread_mutex_unlock(&mutex_liste_threads);
                 return;                  return;
             }              }
   
             pthread_mutex_destroy(&((*s_argument_thread).mutex));              pthread_mutex_destroy(&((*s_argument_thread).mutex));
               pthread_mutex_destroy(&((*s_argument_thread)
                       .mutex_nombre_references));
   
             if ((*s_argument_thread).processus_detache == d_faux)              if ((*s_argument_thread).processus_detache == d_faux)
             {              {
Line 1394  liberation_threads(struct_processus *s_e Line 1334  liberation_threads(struct_processus *s_e
         }          }
         else          else
         {          {
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  pthread_mutex_unlock(&mutex_liste_threads);
                 return;                  return;
             }              }
         }          }
Line 1409  liberation_threads(struct_processus *s_e Line 1350  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 1461  recherche_thread(pid_t pid, pthread_t ti Line 1395  recherche_thread(pid_t pid, pthread_t ti
     return(s_etat_processus);      return(s_etat_processus);
 }  }
   
 static logical1  static struct_processus *
 recherche_thread_principal(pid_t pid, pthread_t *thread)  recherche_thread_principal(pid_t pid)
 {  {
     volatile struct_liste_chainee_volatile      *l_element_courant;      volatile struct_liste_chainee_volatile      *l_element_courant;
   
Line 1486  recherche_thread_principal(pid_t pid, pt Line 1420  recherche_thread_principal(pid_t pid, pt
          * Le processus n'existe plus. On ne distribue aucun signal.           * Le processus n'existe plus. On ne distribue aucun signal.
          */           */
   
         return(d_faux);          return(NULL);
     }      }
   
     (*thread) = (*((struct_thread *) (*l_element_courant).donnee)).tid;      return((*((struct_thread *) (*l_element_courant).donnee))
               .s_etat_processus);
     return(d_vrai);  
 }  }
   
   
Line 1512  recherche_thread_principal(pid_t pid, pt Line 1445  recherche_thread_principal(pid_t pid, pt
 // les sémaphores sont déjà bloqués par un gestionnaire de signal.  // les sémaphores sont déjà bloqués par un gestionnaire de signal.
   
 static inline void  static inline void
 verrouillage_gestionnaire_signaux()  verrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 {  {
     int         semaphore;      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 1556  verrouillage_gestionnaire_signaux() Line 1478  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 1567  verrouillage_gestionnaire_signaux() Line 1493  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 1591  verrouillage_gestionnaire_signaux() Line 1521  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_trywait(&semaphore_liste_threads) == -1)  
 #       else  
         while(sem_trywait(semaphore_liste_threads) == -1)  
 #       endif  
         {          {
             if ((errno != EINTR) && (errno != EAGAIN))  #           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;  
             }  
   
             sched_yield();  
         }          }
     }      }
   
     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 1659  deverrouillage_gestionnaire_signaux() Line 1560  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 1672  deverrouillage_gestionnaire_signaux() Line 1577  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;
 }  }
   
 #ifdef _BROKEN_SIGINFO  /*
   ================================================================================
 // Remplacer les mutexes par des sémaphores SysV    Fonctions de gestion des signaux dans les threads.
   
 #define longueur_queue  256    Lorsqu'un processus reçoit un signal, il appelle le gestionnaire de signal
 #define nombre_queues   13    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é.
   ================================================================================
   */
   
 static int              *fifos;  #define test_signal(signal) \
 static int              segment;      if (signal_test == SIGTEST) { signal_test = signal; return; }
 static sem_t            *semaphores[nombre_queues];  
 static sem_t            *semaphore_global;  
   
 #ifdef IPCS_SYSV  static int          pipe_signaux;
 static unsigned char    *chemin = NULL;  
 #endif  
   
 unsigned char *  logical1
 nom_segment(unsigned char *chemin, pid_t pid)  lancement_thread_signaux(struct_processus *s_etat_processus)
 {  {
     unsigned char               *fichier;      pthread_attr_t                  attributs;
   
 #   ifdef IPCS_SYSV      void                            *argument;
     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);      if (pipe((*s_etat_processus).pipe_signaux) != 0)
 #   else  
     if ((fichier = malloc((1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {      {
         return(NULL);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return(d_erreur);
     }      }
   
     sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);      pipe_signaux = (*s_etat_processus).pipe_signaux[1];
 #   endif  
   
     return(fichier);  
 }  
   
 unsigned char *  
 nom_semaphore(pid_t pid, int queue)  
 {  
     unsigned char               *fichier;  
   
     if ((fichier = malloc((256 + 1) * sizeof(unsigned char))) == NULL)      if (pthread_attr_init(&attributs) != 0)
     {      {
         return(NULL);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return(d_erreur);
     }      }
   
     sprintf(fichier, "/RPL-SIGESMAPHORES-%d-%d", (int) pid, queue);      if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return(d_erreur);
       }
   
     return(fichier);      argument = (*s_etat_processus).pipe_signaux;
 }  
   
 inline int      if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
 queue_de_signal(int signal)              thread_signaux, argument) != 0)
 {  
     switch(signal)  
     {      {
         case SIGINT:          (*s_etat_processus).erreur_systeme = d_es_processus;
             return(0);          return(d_erreur);
         case SIGTSTP:  
             return(1);  
         case SIGCONT:  
             return(2);  
         case SIGURG:  
             return(3);  
         case SIGPIPE:  
             return(4);  
         case SIGALRM:  
             return(5);  
         case SIGFSTOP:  
             return(6);  
         case SIGSTART:  
             return(7);  
         case SIGINJECT:  
             return(8);  
         case SIGABORT:  
             return(9);  
         case SIGFABORT:  
             return(10);  
         case SIGSEGV:  
             return(11);  
         case SIGBUS:  
             return(12);  
     }      }
   
     return(-1);      return(d_absence_erreur);
 }  }
   
 void  logical1
 creation_fifos_signaux(struct_processus *s_etat_processus)  arret_thread_signaux(struct_processus *s_etat_processus)
 {  {
     /*      unsigned char       signal;
      * Signaux utilisés      ssize_t             n;
      * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP,  
      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT  
      */  
   
 #   ifndef IPCS_SYSV // POSIX      signal = (unsigned char ) (rpl_sigmax & 0xFF);
 #   else // SystemV  
   
     file                            *desc;      do
       {
           n = write((*s_etat_processus).pipe_signaux[1], &signal, sizeof(signal));
   
     int                             i;          if (n < 0)
           {
               return(d_erreur);
           }
       } while(n != 1);
   
     key_t                           clef;      pthread_join((*s_etat_processus).thread_signaux, NULL);
   
     unsigned char                   *nom;      close((*s_etat_processus).pipe_signaux[0]);
       close((*s_etat_processus).pipe_signaux[1]);
   
     // Création d'un segment de données associé au PID du processus courant      return(d_absence_erreur);
   }
   
     chemin = (*s_etat_processus).chemin_fichiers_temporaires;  void *
   thread_signaux(void *argument)
   {
       int                     *pipe;
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,      sigset_t                masque;
             getpid())) == NULL)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     if ((desc = fopen(nom, "w")) == NULL)      struct pollfd           fds;
     {  
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;  
         return;  
     }  
   
     fclose(desc);      unsigned char           signal;
   
     if ((clef = ftok(nom, 1)) == -1)      pipe = (int *) argument;
     {      fds.fd = pipe[0];
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;      fds.events = POLLIN;
         return;      fds.revents = 0;
     }  
   
     free(nom);      sigfillset(&masque);
       pthread_sigmask(SIG_BLOCK, &masque, NULL);
   
     if ((segment = shmget(clef,      do
             nombre_queues * (longueur_queue + 4) * sizeof(int),  
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if (poll(&fds, 1, -1) == -1)
         return;          {
     }              pthread_exit(NULL);
           }
   
     fifos = shmat(segment, NULL, 0);          read(fds.fd, &signal, 1);
   
     if (((void *) fifos) == ((void *) -1))          if (signal != (0xFF & rpl_sigmax))
     {  
         if (shmctl(segment, IPC_RMID, 0) == -1)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              envoi_signal_processus(getpid(), signal);
             return;              // Un signal SIGALRM est envoyé par le thread de surveillance
               // des signaux jusqu'à ce que les signaux soient tous traités.
         }          }
       } while(signal != (0xFF & rpl_sigmax));
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;      pthread_exit(NULL);
         return;  }
     }  
   
 #   endif  
   
     /*  // Récupération des signaux
      * Structure d'une queue  // - SIGINT  (arrêt au clavier)
      * 0 : pointeur en lecture sur le premier emplacement libre (int)  // - SIGTERM (signal d'arrêt en provenance du système)
      * 1 : pointeur en écriture sur le premier emplacement à lire (int)  
      * 2 : longueur de la queue (int)  
      * 3 : éléments restants (int)  
      * 4 à 4 + (2) : queue (int)  
      */  
   
     for(i = 0; i < nombre_queues; i++)  void
     {  interruption1(int signal)
         fifos[(i * (longueur_queue + 4))] = 0;  {
         fifos[(i * (longueur_queue + 4)) + 1] = 0;      unsigned char       signal_tronque;
         fifos[(i * (longueur_queue + 4)) + 2] = longueur_queue;  
         fifos[(i * (longueur_queue + 4)) + 3] = longueur_queue;  
     }  
   
     // Création des sémaphores : un sémaphore par signal et par queue      test_signal(signal);
     // plus un sémaphore global pour tous les threads.  
   
     for(i = 0; i < nombre_queues; i++)      switch(signal)
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          case SIGINT:
         {              signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             return;              break;
         }  
   
         // Le sémaphore est créé en écrasant si nécessaire un sémaphore          case SIGTERM:
         // préexistant. Comme le nom du sémaphore contient l'identifiant du              signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
         // processus, il est anormal d'avoir un sémaphore de même nom              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
         // préexistant.              break;
   
         if ((semaphores[i] = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,          case SIGUSR1:
                 1)) == SEM_FAILED)              signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
         {              write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              break;
             return;  
         }  
   
         free(nom);          default:
               // SIGALRM
               break;
     }      }
   
       return;
   }
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)  // Récupération des signaux
     {  // - SIGFSTP
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  //
         return;  // 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.
   
     if ((semaphore_global = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,  void
             1)) == SEM_FAILED)  interruption2(int signal)
     {  {
         (*s_etat_processus).erreur_systeme = d_es_semaphore;      unsigned char       signal_tronque;
         return;  
     }  
   
     free(nom);      test_signal(signal);
   
       signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
       write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     return;      return;
 }  }
   
 void  void
 liberation_fifos_signaux(struct_processus *s_etat_processus)  interruption3(int signal)
 {  {
     int                 i;      // 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 (shmdt(fifos) == -1)      if (pid_processus_pere == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          kill(pid_processus_pere, SIGUSR1);
         return;  
     }      }
   
     for(i = 0; i < nombre_queues; i++)      if (signal != SIGUSR2)
     {      {
         if (sem_close(semaphores[i]) != 0)          write(STDERR_FILENO, message_1, strlen(message_1));
         {  
             (*s_etat_processus).erreur_systeme = d_es_semaphore;  
             return;  
         }  
     }      }
       else
     if (sem_close(semaphore_global) != 0)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_semaphore;          write(STDERR_FILENO, message_2, strlen(message_2));
         return;  
     }      }
   
       _exit(EXIT_FAILURE);
   }
   
   // Récupération des signaux
   // - SIGHUP
   
   void
   interruption4(int signal)
   {
       unsigned char       signal_tronque;
   
       test_signal(signal);
   
       signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
       write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     return;      return;
 }  }
   
   // Récupération des signaux
   // - SIGPIPE
   
 void  void
 destruction_fifos_signaux(struct_processus *s_etat_processus)  interruption5(int signal)
 {  {
     int                 i;      unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
       unsigned char       signal_tronque;
   
     unsigned char       *nom;      test_signal(signal);
   
     if (shmdt(fifos) == -1)      if (pid_processus_pere == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
         return;          write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
     }      }
   
     if (shmctl(segment, IPC_RMID, 0) == -1)      write(STDERR_FILENO, message, strlen(message));
       return;
   }
   
   inline static void
   signal_alrm(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
       if (pid == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Si pid est égal à getpid(), le signal à traiter est issu
         return;          // du même processus que celui qui va le traiter, mais d'un thread
     }          // différent.
   
           if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,          if ((*s_etat_processus).pid_processus_pere != getpid())
             getpid())) == NULL)          {
               // On n'est pas dans le processus père, on remonte le signal.
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigalrm);
           }
           else
           {
               // On est dans le processus père, on effectue un arrêt d'urgence.
               (*s_etat_processus).var_volatile_alarme = -1;
               (*s_etat_processus).var_volatile_requete_arret = -1;
           }
       }
       else
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Le signal est issu d'un processus différent. On recherche le
         return;          // thread principal pour remonter le signal.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
           }
     }      }
   
     unlink(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
     free(nom);      return;
   }
   
   inline static void
   signal_term(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
       pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
     for(i = 0; i < nombre_queues; i++)      if (pid == getpid())
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
             return;                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
   
         if (sem_unlink(nom) != 0)          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
             return;                      rpl_sigterm);
         }          }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
         free(nom);              pthread_mutex_lock(&exclusion);
     }  
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)              if ((*s_etat_processus).var_volatile_requete_arret == -1)
     {              {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  deverrouillage_gestionnaire_signaux(s_etat_processus);
         return;                  pthread_mutex_unlock(&exclusion);
     }                  return;
               }
   
               (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
     if (sem_unlink(nom) != 0)              pthread_mutex_unlock(&exclusion);
           }
       }
       else
     {      {
         (*s_etat_processus).erreur_systeme = d_es_semaphore;          if ((s_thread_principal = recherche_thread_principal(getpid()))
         return;                  != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigterm);
           }
     }      }
   
     free(nom);      deverrouillage_gestionnaire_signaux(s_etat_processus);
   
     return;      return;
 }  }
   
 int  inline static void
 queue_in(pid_t pid, int signal)  signal_int(struct_processus *s_etat_processus, pid_t pid)
 {  {
 #undef printf      struct_processus        *s_thread_principal;
 // Transformer ce truc en POSIX ! On ne fait du SysV que si on n'a pas le choix      volatile sig_atomic_t   exclusion = 0;
   
 #   ifndef IPCS_SYSV      verrouillage_gestionnaire_signaux(s_etat_processus);
 #   else // Traitement à l'aide d'IPCS SystemV  
   
     int             *base;      if (pid == getpid())
     int             *buffer;      {
     int             *projection_fifos;          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     int             queue;          {
     int             identifiant;              printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     key_t           clef;          if ((*s_etat_processus).pid_processus_pere != getpid())
           {
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigint);
           }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
     sem_t           *semaphore;              while(exclusion == 1);
               exclusion = 1;
   
     struct stat     s_stat;              if ((*s_etat_processus).var_volatile_requete_arret == -1)
               {
                   deverrouillage_gestionnaire_signaux(s_etat_processus);
                   exclusion = 0;
                   return;
               }
   
     unsigned char   *nom;              if ((*s_etat_processus).langue == 'F')
               {
                   printf("+++Interruption\n");
               }
               else
               {
                   printf("+++Interrupt\n");
               }
   
     queue = queue_de_signal(signal);              fflush(stdout);
   
     // Ouverture des projections              (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
     if ((nom = nom_segment(chemin, pid)) == NULL)              exclusion = 0;
           }
       }
       else
     {      {
         return(-1);          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigint);
           }
     }      }
   
     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,      deverrouillage_gestionnaire_signaux(s_etat_processus);
     // il convient d'attendre que le fichier support soit effectivement      return;
     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il  }
     // n'existe plus, le processus associé n'existe plus.  
   
     if (signal == SIGSTART)  static inline void
     {  signal_tstp(struct_processus *s_etat_processus, pid_t pid)
         // On attend que le fichier sois présent  {
       struct_processus        *s_thread_principal;
   
         while(stat(nom, &s_stat) != 0);      verrouillage_gestionnaire_signaux(s_etat_processus);
     }  
   
     if ((clef = ftok(nom, 1)) == -1)      if (pid == getpid())
     {      {
         return(-1);          /*
     }           *  0 => fonctionnement normal
            * -1 => requête
            *  1 => requête acceptée en attente de traitement
            */
   
     free(nom);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
           {
               printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
     if (signal == SIGSTART)          if ((*s_etat_processus).var_volatile_processus_pere == 0)
     {          {
         while((identifiant = shmget(clef,              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                 nombre_queues * (longueur_queue + 4) * sizeof(int),                      rpl_sigtstp);
                 S_IRUSR | S_IWUSR)) == -1);          }
           else
           {
               (*s_etat_processus).var_volatile_requete_arret2 = -1;
           }
     }      }
     else      else
     {      {
         if ((identifiant = shmget(clef,          // Envoi d'un signal au thread maître du groupe.
                 nombre_queues * (longueur_queue + 4) * sizeof(int),  
                 S_IRUSR | S_IWUSR)) == -1)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             return(-1);              envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
         }          }
     }      }
   
     projection_fifos = shmat(identifiant, NULL, 0);      deverrouillage_gestionnaire_signaux(s_etat_processus);
       return;
   }
   
     if (((void *) projection_fifos) == ((void *) -1))  static void
   sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
   {
       switch((*((volatile int *) arg1)))
     {      {
         return(-1);          case 1:
     }              longjmp(contexte_ecriture, -1);
               break;
   
     if ((nom = nom_semaphore(pid, queue)) == NULL)          case 2:
     {              longjmp(contexte_impression, -1);
         shmdt(projection_fifos);              break;
         return(-1);  
     }      }
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);      return;
   }
   
     if (sem_wait(semaphore) != 0)  void
   interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
   {
       if ((urgence == 0) && (routine_recursive != 0))
     {      {
         shmdt(projection_fifos);          // On peut tenter de récupérer le dépassement de pile. Si la variable
         return(-1);          // 'routine_recursive' est non nulle, on récupère l'erreur.
   
           sigsegv_leave_handler(sortie_interruption_depassement_pile,
                   (void *) &routine_recursive, NULL, NULL);
     }      }
   
     // Il ne faut pas empiler plusieurs SIGSTART car SIGSTART peut provenir      // Ici, la panique est totale et il vaut mieux quitter l'application.
     // de l'instruction SWI. Plusieurs threads peuvent interrompre de façon      interruption3(SIGUSR2);
     // asynchrone le processus père durant une phase de signaux masqués.      return;
   }
   
     base = &(projection_fifos[(longueur_queue + 4) * queue]);  int
     buffer = &(base[4]);  interruption_violation_access(void *adresse_fautive, int gravite)
   {
       unsigned char       message[] = "+++System : Trying to catch access "
                                   "violation\n";
   
     // base[3] contient le nombre d'éléments restants      static int          compteur_erreur = 0;
   
     if (base[3] <= 0)      if ((gravite == 0) && (routine_recursive != 0))
     {      {
         sem_post(semaphore);          // Il peut s'agir d'un dépassement de pile.
         sem_close(semaphore);  
         shmdt(projection_fifos);  
         return(-1);  
     }  
   
     base[3]--;          sigsegv_leave_handler(sortie_interruption_depassement_pile,
                   (void *) &routine_recursive, NULL, NULL);
     // base[1] contient le prochain élément à écrire  
     buffer[base[1]++] = (int) pid;  
     base[1] %= base[2];  
   
     if (sem_post(semaphore) != 0)  
     {  
         shmdt(projection_fifos);  
         sem_close(semaphore);  
         return(-1);  
     }      }
   
     sem_close(semaphore);      // On est dans une bonne vieille violation d'accès. On essaie
       // de fermer au mieux l'application.
     // Fermeture des projections  
     shmdt(projection_fifos);  
   
 #   endif  
   
     return(0);  
 }  
   
 pid_t  
 origine_signal(int signal)  
 {  
     int             *base;  
     int             *buffer;  
     int             pid;  
     int             queue;  
   
     queue = queue_de_signal(signal);  
   
     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",      compteur_erreur++;
             (int) getpid(), signal));  
   
     if (sem_wait(semaphores[queue]) != 0)      if (compteur_erreur >= 2)
     {      {
         return(-1);          // Erreurs multiples, on arrête l'application.
           interruption3(SIGSEGV);
           return(0);
     }      }
   
     // Le signal SIGCONT peut être envoyé de façon totalement asynchrone.      write(STDERR_FILENO, message, strlen(message));
     // Il peut y avoir plus de signaux envoyés que d'interruptions traitées.  
     // Il convient donc de rectifier la queue lors du traitement de  
     // l'interruption correspondante. Le gestionnaire étant installé sans  
     // l'option NODEFER, la queue reste cohérente.  
   
     if (signal == SIGCONT)      if (pid_processus_pere == getpid())
     {      {
         base = &(fifos[(longueur_queue + 4) * queue]);          longjmp(contexte_initial, -1);
         buffer = &(base[4]);          return(1);
         base[0] = (base[1] - 1) % base[2];  
         pid = buffer[base[0]++];  
         base[3] = base[2];  
     }      }
     else      else
     {      {
         base = &(fifos[(longueur_queue + 4) * queue]);          longjmp(contexte_processus, -1);
         buffer = &(base[4]);          return(1);
         pid = buffer[base[0]++];  
         base[0] %= base[2];  
         base[3]++;  
     }      }
   
     if (base[3] > base[2])      // On renvoie 0 parce qu'on décline toute responsabilité quant à la
     {      // suite des événements...
         sem_post(semaphores[queue]);      return(0);
         return(-1);  
     }  
   
     if (sem_post(semaphores[queue]) != 0)  
     {  
         return(-1);  
     }  
   
     return((pid_t) pid);  
 }  }
   
 #endif  // Traitement de rpl_sigstart
   
 #ifdef printf  
 #   undef printf  
 #endif  
   
 void  static inline void
 interruption1(SIGHANDLER_ARGS)  signal_start(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t                   pid;      struct_processus        *s_thread_principal;
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;      verrouillage_gestionnaire_signaux(s_etat_processus);
   
     volatile sig_atomic_t   exclusion = 0;      if (pid == getpid())
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     if (signal == SIGINT)  
     {      {
         // Si l'interruption provient du clavier, il n'y a pas eu d'appel          (*s_etat_processus).demarrage_fils = d_vrai;
         // à queue_in().  
   
         pid = getpid();  
     }      }
     else      else
     {      {
         pid = origine_signal(signal);          // Envoi d'un signal au thread maître du groupe.
     }  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     switch(signal)          if ((s_thread_principal = recherche_thread_principal(getpid()))
     {                  != NULL)
         case SIGALRM :  
         {          {
             if (pid == getpid())              envoi_signal_contexte(s_thread_principal, rpl_sigstart);
             {  
                 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] SIGALRM (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())  
                 {  
                     kill((*s_etat_processus).pid_processus_pere, signal);  
                 }  
                 else  
                 {  
                     (*s_etat_processus).var_volatile_alarme = -1;  
                     (*s_etat_processus).var_volatile_requete_arret = -1;  
                 }  
             }  
             else  
             {  
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }  
   
             break;  
         }          }
       }
   
         case SIGINT :      deverrouillage_gestionnaire_signaux(s_etat_processus);
         {      return;
             /*  }
              * Une vieille spécification POSIX permet au pointeur siginfo  
              * d'être nul dans le cas d'un ^C envoyé depuis le clavier.  
              * Solaris suit en particulier cette spécification.  
              */  
   
 #           ifndef _BROKEN_SIGINFO  
             if (siginfo == NULL)  
             {  
                 kill(getpid(), signal);  
             }  
             else  
 #           endif  
             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)  
                 {  
                     printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())  
                 {  
                     kill((*s_etat_processus).pid_processus_pere, signal);  
                 }  
                 else  
                 {  
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;  
   
                     while(exclusion == 1);  
                     exclusion = 1;  
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)  
                     {  
                         deverrouillage_gestionnaire_signaux();  
                         exclusion = 0;  
                         return;  
                     }  
   
                     if (strncmp(getenv("LANG"), "fr", 2) == 0)  
                     {  
                         printf("+++Interruption\n");  
                     }  
                     else  
                     {  
                         printf("+++Interrupt\n");  
                     }  
   
                     fflush(stdout);  // Traitement de rpl_sigcont
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;  static inline void
                     (*s_etat_processus).var_volatile_alarme = -1;  signal_cont(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
                     exclusion = 0;      verrouillage_gestionnaire_signaux(s_etat_processus);
                 }  
             }  
             else  
             {  
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }  
   
             break;      if (pid == getpid())
         }      {
           (*s_etat_processus).redemarrage_processus = d_vrai;
       }
       else
       {
           // Envoi d'un signal au thread maître du groupe.
   
         default :          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             BUG(1, uprintf("[%d] Unknown signal %d in this context\n",              envoi_signal_contexte(s_thread_principal, rpl_sigcont);
                     (int) getpid(), signal));  
             break;  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigstop
 interruption2(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  static inline void
   signal_stop(struct_processus *s_etat_processus, pid_t pid)
     struct_processus        *s_etat_processus;  {
       struct_processus        *s_thread_principal;
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
 #   ifndef _BROKEN_SIGINFO      verrouillage_gestionnaire_signaux(s_etat_processus);
     if (siginfo == NULL)  
     {  
         /*  
          * Le signal SIGFSTP provient de la mort du processus de contrôle.  
          * Sous certains systèmes (Linux...), la mort du terminal de contrôle  
          * se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres  
          * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo  
          * non initialisée (pointeur NULL) issue de TERMIO.  
          */  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
         {  
             pthread_kill(thread, SIGHUP);  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
     }  
     else  
 #   endif  
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         /*  
          *  0 => fonctionnement normal  
          * -1 => requête  
          *  1 => requête acceptée en attente de traitement  
          */  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGTSTP (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);
         }          }
   
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          /*
            * var_globale_traitement_retarde_stop :
            *  0 -> traitement immédiat
            *  1 -> traitement retardé (aucun signal reçu)
            * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
            */
   
           if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
         {          {
             kill((*s_etat_processus).pid_processus_pere, signal);              (*s_etat_processus).var_volatile_requete_arret = -1;
         }          }
         else          else
         {          {
             (*s_etat_processus).var_volatile_requete_arret2 = -1;              (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
         }          }
     }      }
     else      else
     {      {
         // 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, SIGTSTP);              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
 interruption3(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     static int              compteur = 0;  
   
     verrouillage_gestionnaire_signaux();  static inline void
   signal_inject(struct_processus *s_etat_processus, pid_t pid)
 #   ifdef _BROKEN_SIGINFO  {
     pid = origine_signal(signal);      verrouillage_gestionnaire_signaux(s_etat_processus);
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     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] SIGSEGV (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);
     }      }
   
     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);  
     }  
     else  
     {  
         // Segfault dans une routine interne  
         if (strncmp(getenv("LANG"), "fr", 2) == 0)  
         {  
             printf("+++Système : Violation d'accès (dépassement de pile)\n");  
         }  
         else  
         {  
             printf("+++System : Access violation (stack overflow)\n");  
         }  
   
         fflush(stdout);  
   
         compteur++;  static inline void
   signal_urg(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
       verrouillage_gestionnaire_signaux(s_etat_processus);
   
         if (compteur > 1)      if (pid == getpid())
       {
           if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             deverrouillage_gestionnaire_signaux();              printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
             exit(EXIT_FAILURE);                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
         else  
           (*s_etat_processus).var_volatile_alarme = -1;
           (*s_etat_processus).var_volatile_requete_arret = -1;
       }
       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_sigurg);
             longjmp(contexte_initial, -1);  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigabort
 interruption4(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  static inline void
   signal_abort(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux(s_etat_processus);
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     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;
     }      }
   
     /*  
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)  
      */  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGSTART/SIGCONT (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);
     }      }
   
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 void  
 interruption5(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     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()))          (*s_etat_processus).arret_depuis_abort = -1;
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
         {  
             printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),  
                     (unsigned long long) pthread_self());  
             fflush(stdout);  
         }  
   
         /*          /*
          * var_globale_traitement_retarde_stop :           * var_globale_traitement_retarde_stop :
Line 2629  interruption5(SIGHANDLER_ARGS) Line 2373  interruption5(SIGHANDLER_ARGS)
     }      }
     else      else
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          (*s_etat_processus).arret_depuis_abort = -1;
                 == 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_sigabort);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux(s_etat_processus);
     return;      return;
 }  }
   
 void  
 interruption6(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  static inline void
   signal_hup(struct_processus *s_etat_processus, pid_t pid)
   {
       file                    *fichier;
   
     verrouillage_gestionnaire_signaux();      unsigned char           nom[8 + 64 + 1];
   
 #   ifdef _BROKEN_SIGINFO      verrouillage_gestionnaire_signaux(s_etat_processus);
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     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;
     }      }
   
       snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),
               (unsigned long) pthread_self());
   
       if ((fichier = fopen(nom, "w+")) != NULL)
       {
           fclose(fichier);
   
           freopen(nom, "w", stdout);
           freopen(nom, "w", stderr);
       }
   
       freopen("/dev/null", "r", stdin);
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGINJECT/SIGQUIT (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
 interruption7(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);
     struct_processus        *s_etat_processus;      return;
   }
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  static inline void
     pid = origine_signal(signal);  signal_except(struct_processus *s_etat_processus, pid_t pid)
 #   else  {
     pid = (*siginfo).si_pid;      verrouillage_gestionnaire_signaux(s_etat_processus);
 #   endif  
   
     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)      (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
       deverrouillage_gestionnaire_signaux(s_etat_processus);
   
       return;
   }
   
   static inline void
   envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
           pid_t pid_source)
   {
       switch(signal)
     {      {
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),          case rpl_signull:
                 (unsigned long long) pthread_self());              break;
         fflush(stdout);  
     }          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;
   
     (*s_etat_processus).var_volatile_requete_arret = -1;          case rpl_sigtstp:
     deverrouillage_gestionnaire_signaux();              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;
       }
   
     BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));  
     return;      return;
 }  }
   
 void  void
 interruption8(SIGHANDLER_ARGS)  scrutation_interruptions(struct_processus *s_etat_processus)
 {  {
     pid_t                   pid;      // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();      // 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.
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              envoi_interruptions(s_etat_processus,
         {                      (*s_queue_signaux).queue[(*s_queue_signaux)
             printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),                      .pointeur_lecture].signal, (*s_queue_signaux).queue
                     (unsigned long long) pthread_self());                      [(*s_queue_signaux).pointeur_lecture].pid);
             fflush(stdout);              (*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).var_volatile_alarme = -1;  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
         (*s_etat_processus).var_volatile_requete_arret = -1;              sem_post(&((*s_queue_signaux).semaphore));
   #       else
               sem_post(semaphore_queue_signaux);
   #       endif
     }      }
     else  
     {  
         // Envoi d'un signal au thread maître du groupe.  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)      // 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)
         {          {
             pthread_kill(thread, SIGURG);              // Il y a un signal dans la queue du thread courant. On le traite.
             deverrouillage_gestionnaire_signaux();  
             return;              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);
     }      }
   
     deverrouillage_gestionnaire_signaux();  
     return;      return;
 }  }
   
 void  /*
 interruption9(SIGHANDLER_ARGS)  ================================================================================
     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)
 {  {
     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)
           {
               return(NULL);
           }
   
           sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
   #   endif
   
       return(fichier);
   }
   
   
     struct_processus        *s_etat_processus;  /*
   ================================================================================
     Fonctions d'envoi d'un signal à un thread ou à un processus.
   ================================================================================
     Entrée : processus et signal
   --------------------------------------------------------------------------------
     Sortie : erreur
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
     verrouillage_gestionnaire_signaux();  int
   envoi_signal_processus(pid_t pid, enum signaux_rpl signal)
   {
   #   ifndef OS2
           int                         segment;
   #   endif
   
 #   ifdef _BROKEN_SIGINFO  #   ifndef IPCS_SYSV
     pid = origine_signal(signal);  #       ifdef SEMAPHORES_NOMMES
               sem_t                   *semaphore;
               sem_t                   *signalisation;
   #       endif
 #   else  #   else
     pid = (*siginfo).si_pid;  #       ifndef OS2
               int                     desc;
               key_t                   clef;
   #       endif
 #   endif  #   endif
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      struct_queue_signaux            *queue;
     {  
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      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())
     {      {
         printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),          // Le signal est envoyé au même processus.
                 (unsigned long long) pthread_self());  
         fflush(stdout);          if (s_queue_signaux == NULL)
     }          {
               return(1);
           }
   
   #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               while(sem_wait(&((*s_queue_signaux).semaphore)) != 0)
   #       else
               while(sem_wait(semaphore_queue_signaux) != 0)
   #       endif
           {
               if (errno != EINTR)
               {
                   return(1);
               }
           }
   
           (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .pid = pid;
           (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
                   .signal = signal;
   
           (*s_queue_signaux).pointeur_ecriture =
                   ((*s_queue_signaux).pointeur_ecriture + 1)
                   % LONGUEUR_QUEUE_SIGNAUX;
   
 #   ifdef _BROKEN_SIGINFO  #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     if (queue_in(getpid(), signal) != 0)              if (sem_post(&((*s_queue_signaux).semaphore)) != 0)
   #       else
               if (sem_post(semaphore_queue_signaux) != 0)
   #       endif
           {
               return(1);
           }
   
   #       if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
               if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
   #       else
               if (sem_post(semaphore_signalisation) != 0)
   #       endif
           {
               return(1);
           }
       }
       else
     {      {
         return;          // Le signal est envoyé depuis un processus distinct.
   
   #       ifdef IPCS_SYSV
               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
     }      }
   
     deverrouillage_gestionnaire_signaux();      return(0);
     interruption11(signal);  
 #   else  
     deverrouillage_gestionnaire_signaux();  
     interruption11(signal, siginfo, context);  
 #   endif  
     return;  
 }  }
   
 void  int
 interruption10(SIGHANDLER_ARGS)  envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
 {  {
     file                    *fichier;      // Un signal est envoyé d'un thread à un autre thread du même processus.
   
     pid_t                   pid;      volatile struct_liste_chainee_volatile  *l_element_courant;
   
     struct_processus        *s_etat_processus;      struct_processus                        *s_etat_processus;
   
     unsigned char           nom[8 + 64 + 1];      if (pthread_mutex_lock(&mutex_liste_threads) != 0)
       {
     verrouillage_gestionnaire_signaux();          return(1);
       }
   
 #   ifdef _BROKEN_SIGINFO      l_element_courant = liste_threads;
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      while(l_element_courant != NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          if (((*((struct_thread *) (*l_element_courant).donnee)).pid
         return;                  == getpid()) && (pthread_equal((*((struct_thread *)
                   (*l_element_courant).donnee)).tid, tid) != 0))
           {
               break;
           }
   
           l_element_courant = (*l_element_courant).suivant;
     }      }
   
     snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),      if (l_element_courant == NULL)
             (unsigned long) pthread_self());      {
           pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
     if ((fichier = fopen(nom, "w+")) != NULL)      if (pthread_mutex_lock(&mutex_interruptions) != 0)
     {      {
         fclose(fichier);          pthread_mutex_unlock(&mutex_liste_threads);
           return(1);
       }
   
         freopen(nom, "w", stdout);      s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
         freopen(nom, "w", stderr);              .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);
     }      }
   
     freopen("/dev/null", "r", stdin);      if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
       {
           return(1);
       }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
       if (sem_post(&((*s_queue_signaux).signalisation)) != 0)
     {      {
         printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),          return(1);
                 (unsigned long long) pthread_self());      }
         fflush(stdout);  #   else
       if (sem_post(semaphore_signalisation) != 0)
       {
           return(1);
     }      }
   #   endif
   
     deverrouillage_gestionnaire_signaux();      return(0);
     return;  
 }  }
   
 void  int
 interruption11(SIGHANDLER_ARGS)  envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
           enum signaux_rpl signal)
 {  {
     pid_t                   pid;      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);
   
     pthread_t               thread;  #   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
   
     struct_processus        *s_etat_processus;      return(0);
   }
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  /*
     pid = origine_signal(signal);  ================================================================================
 #   else    Fonction créant un segment de mémoire partagée destiné à contenir
     pid = (*siginfo).si_pid;    la queue des signaux.
 #   endif  ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
     if (pid == getpid())  void
     {  creation_queue_signaux(struct_processus *s_etat_processus)
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  {
                 == NULL)      pthread_attr_t                  attributs;
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         (*s_etat_processus).arret_depuis_abort = -1;      unsigned char                   *nom;
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 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)
         {          {
             printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(),              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                     (unsigned long long) pthread_self());              return;
             fflush(stdout);  
         }          }
   
         /*          if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
          * var_globale_traitement_retarde_stop :                  S_IRUSR | S_IWUSR)) == -1)
          *  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;              free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
         else  
           if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
         {          {
             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;              free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
         }          }
     }  
     else          s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
     {                  PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)          if (((void *) s_queue_signaux) == ((void *) -1))
         {          {
             deverrouillage_gestionnaire_signaux();              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;              return;
         }          }
   
         (*s_etat_processus).arret_depuis_abort = -1;          free(nom);
   
         // Envoi d'un signal au thread maître du groupe.  #       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
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          (*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))
         {          {
             pthread_kill(thread, signal);              (*s_etat_processus).erreur_systeme = d_es_processus;
             deverrouillage_gestionnaire_signaux();  
             return;              return;
         }          }
     }  #   else // IPCS_SYSV
   #       ifndef OS2
               int                             segment;
               int                             support;
   
     deverrouillage_gestionnaire_signaux();              key_t                           clef;
     return;  
 }  
   
 void              // Création d'un segment de données associé au PID du processus
 traitement_exceptions_gsl(const char *reason, const char *file,              // courant
         int line, int gsl_errno)  
 {  
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();              if ((nom = nom_segment((*s_etat_processus)
                       .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)              if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
     {                      S_IRUSR | S_IWUSR)) == -1)
         deverrouillage_gestionnaire_signaux();              {
         return;                  (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
     }                  return;
               }
   
     (*s_etat_processus).var_volatile_exception_gsl = gsl_errno;              if ((clef = ftok(nom, 1)) == -1)
     deverrouillage_gestionnaire_signaux();              {
     return;                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 }                  return;
               }
   
 #ifdef _BROKEN_SIGINFO              close(support);
               free(nom);
   
 #undef kill              if ((segment = shmget(clef, sizeof(struct_queue_signaux),
 #undef pthread_kill                      IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
 int              s_queue_signaux = shmat(segment, NULL, 0);
 kill_broken_siginfo(pid_t pid, int signal)              f_queue_signaux = segment;
 {  
     int                 ios;              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;
               }
   
     sem_t               *semaphore;              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;
               }
   
     unsigned char       *nom;              free(nom);
   
     /*              sem_init(&((*s_queue_signaux).semaphore), 1, 1);
      * Lorsqu'on veut interrompre le processus pid, on ouvre le segment              sem_init(&((*s_queue_signaux).signalisation), 1, 0);
      * correspondant au processus en question et ou ajoute le pid dans la              (*s_queue_signaux).pointeur_lecture = 0;
      * queue.              (*s_queue_signaux).pointeur_ecriture = 0;
      *              (*s_queue_signaux).requete_arret = d_faux;
      * Le sémaphore global à tous les threads d'un même processus sert  #       endif
      * à garantir que les signaux seront traités dans l'ordre de ce qui est  #   endif
      * effectivement mis dans la queue.  
      */  
   
     // Sémaphore acquis      // Lancement du thread de récupération des signaux.
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)      if (pthread_attr_init(&attributs) != 0)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
     }      }
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      if (pthread_attr_setdetachstate(&attributs,
               PTHREAD_CREATE_JOINABLE) != 0)
     {      {
         free(nom);          (*s_etat_processus).erreur_systeme = d_es_processus;
         return(-1);          return;
       }
   
   #   ifdef SCHED_OTHER
       if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
     }      }
   #   endif
   
   #   ifdef PTHREAD_EXPLICIT_SCHED
       if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   #   endif
   
     free(nom);  #   ifdef PTHREAD_SCOPE_SYSTEM
       if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   #   endif
   
     if (sem_wait(semaphore) == -1)      if (pthread_attr_destroy(&attributs) != 0)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
     }      }
   
     if ((signal != 0) && (signal != SIGINT))      if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
               thread_surveillance_signaux, s_etat_processus) != 0)
     {      {
         if (queue_in(pid, signal) != 0)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return;
             sem_post(semaphore);  
             sem_close(semaphore);  
             return(-1);  
         }  
     }      }
   
     ios = kill(pid, signal);      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
   ================================================================================
   */
   
     // Sémaphore relâché  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
   
     sem_post(semaphore);      pthread_join((*s_queue_signaux).thread_signaux, NULL);
     sem_close(semaphore);  
   
     return(ios);  #   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;
 }  }
   
 int  
 pthread_kill_broken_siginfo(pthread_t tid, int signal)  /*
   ================================================================================
     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)
 {  {
     int                 ios;  #   ifndef OS2
           unsigned char       *nom;
   #   endif
   
     sem_t               *semaphore;      // Incrémenter le sémaphore pour être sûr de le débloquer.
   
     unsigned char       *nom;      (*s_queue_signaux).requete_arret = d_vrai;
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)  #   if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV)
     {      sem_post(&((*s_queue_signaux).signalisation));
         return(-1);  #   else
     }      sem_post(semaphore_signalisation);
   #   endif
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      pthread_join((*s_queue_signaux).thread_signaux, NULL);
     {  
         free(nom);  
         return(-1);  
     }  
   
     free(nom);  #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
               // Il faut commencer par éliminer le sémaphore.
   
     if (sem_wait(semaphore) == -1)              if (semctl((*s_queue_signaux).semaphore.sem, 0, IPC_RMID) == -1)
     {              {
         return(-1);                  (*s_etat_processus).erreur_systeme = d_es_processus;
     }                  return;
               }
   
     if ((signal != 0) && (signal != SIGINT))              unlink((*s_queue_signaux).semaphore.path);
     {              free((*s_queue_signaux).semaphore.path);
         if (queue_in(getpid(), signal) != 0)  
               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)
         {          {
             sem_post(semaphore);              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             sem_close(semaphore);              return;
             return(-1);  
         }          }
     }  
   
     ios = pthread_kill(tid, signal);          if ((nom = nom_segment(NULL, getpid())) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     sem_post(semaphore);          close(f_queue_signaux);
     sem_close(semaphore);  
   
     return(ios);          if (shm_unlink(nom) != 0)
 }          {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
 #endif          free(nom);
   #   endif
   
       return;
   }
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.33  
changed lines
  Added in v.1.112


CVSweb interface <joel.bertrand@systella.fr>