Diff for /rpl/src/interruptions.c between versions 1.69 and 1.198

version 1.69, 2011/09/15 17:51:43 version 1.198, 2018/12/24 15:56:35
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.1.3    RPL/2 (R) version 4.1.30
   Copyright (C) 1989-2011 Dr. BERTRAND Joël    Copyright (C) 1989-2018 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;  static volatile int                             code_erreur_gsl = 0;
   
 static unsigned char                            *racine_segment;  unsigned char                                   *racine_segment;
   
   static void *
   thread_surveillance_signaux(void *argument)
   {
       // Cette fonction est lancée dans un thread créé par processus pour
       // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du
       // signal SIGUSR2. Les processus externes n'envoient plus un signal au
       // processus ou au thread à signaler mais positionnent les informations
       // nécessaires dans la queue des signaux et incrémentent le sémaphore.
       // Le sémaphore est décrémenté lorsque le signal est effectivement traité.
   
       int                                     ios;
       int                                     nombre_signaux_envoyes;
   
       struct_processus                        *s_etat_processus;
   
       struct timespec                         attente;
   
       volatile struct_liste_chainee_volatile  *l_element_courant;
   
       sigset_t                                set;
   
       sigfillset(&set);
       pthread_sigmask(SIG_BLOCK, &set, NULL);
   
       s_etat_processus = (struct_processus *) argument;
   
       for(;;)
       {
           attente.tv_sec = 0;
           attente.tv_nsec = GRANULARITE_us * 1000;
   
           if (sem_wait(semaphore_signalisation) == 0)
           {
               while((ios = sem_wait(semaphore_arret_signalisation)) != 0)
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                   }
               }
   
               if ((*s_queue_signaux).requete_arret == d_vrai)
               {
                   sem_post(semaphore_arret_signalisation);
                   sem_post(semaphore_signalisation);
   
                   break;
               }
   
               sem_post(semaphore_signalisation);
   
               nombre_signaux_envoyes = 0;
   
               // Dans un premier temps, on verrouille la queue des signaux
               // affectée au processus courant pour vérifier s'il y a quelque
               // chose à traiter.
   
               while((ios = sem_wait(semaphore_queue_signaux)) != 0)
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                   }
               }
   
               if ((*s_queue_signaux).pointeur_lecture !=
                       (*s_queue_signaux).pointeur_ecriture)
               {
                   // Attention : raise() envoit le signal au thread appelant !
                   // kill() l'envoie au processus appelant, donc dans notre
                   // cas à un thread aléatoire du processus, ce qui nous
                   // convient tout à fait puisqu'il s'agit de débloquer les
                   // appels système lents.
   
                   nombre_signaux_envoyes++;
                   kill(getpid(), SIGUSR2);
                   sched_yield();
               }
   
               sem_post(semaphore_queue_signaux);
               sem_post(semaphore_arret_signalisation);
   
               // Dans un second temps, on balaye toutes les queues de signaux
               // des threads du processus courant.
   
               // Attention : l'ordre de verrouillage des mutexes est important
               // pour éviter les conditions bloquantes !
   
               pthread_mutex_lock(&mutex_liste_threads);
   
               l_element_courant = liste_threads;
   
               while(l_element_courant != NULL)
               {
                   if ((*((struct_thread *) (*l_element_courant).donnee)).pid
                           == getpid())
                   {
                       pthread_mutex_lock(&((*(*((struct_thread *)
                               (*l_element_courant).donnee)).s_etat_processus)
                               .mutex_signaux));
   
                       if ((*(*((struct_thread *) (*l_element_courant).donnee))
                               .s_etat_processus).pointeur_signal_ecriture !=
                               (*(*((struct_thread *) (*l_element_courant)
                               .donnee)).s_etat_processus).pointeur_signal_lecture)
                       {
                           nombre_signaux_envoyes++;
                           pthread_kill((*((struct_thread *)
                                   (*l_element_courant).donnee)).tid, SIGUSR2);
                           sched_yield();
                       }
   
                       pthread_mutex_unlock(&((*(*((struct_thread *)
                               (*l_element_courant).donnee)).s_etat_processus)
                               .mutex_signaux));
                   }
   
                   l_element_courant = (*l_element_courant).suivant;
               }
   
               pthread_mutex_unlock(&mutex_liste_threads);
   
               // Nanosleep
   
               if (nombre_signaux_envoyes > 0)
               {
                   nanosleep(&attente, NULL);
               }
           }
           else
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
               }
           }
       }
   
 static pthread_mutex_t                          mutex_interruptions      pthread_exit(NULL);
         = PTHREAD_MUTEX_INITIALIZER;  }
   
 void  void
 modification_pid_thread_pere(struct_processus *s_etat_processus)  modification_pid_thread_pere(struct_processus *s_etat_processus)
Line 207  retrait_thread(struct_processus *s_etat_ Line 344  retrait_thread(struct_processus *s_etat_
         return;          return;
     }      }
   
       // Le thread ne peut plus traiter de signaux explicites. Il convient
       // alors de corriger le sémaphore pour annuler les signaux en attente.
   
       while((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
               .pointeur_signal_ecriture != (*(*((struct_thread *)
               (*l_element_courant).donnee)).s_etat_processus)
               .pointeur_signal_lecture)
       {
           while(sem_wait(semaphore_signalisation) != 0)
           {
               if (errno != EINTR)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
           }
   
           (*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
                   .pointeur_signal_lecture = ((*(*((struct_thread *)
                   (*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);
   
Line 324  verrouillage_threads_concurrents(struct_ Line 484  verrouillage_threads_concurrents(struct_
                 == getpid()) && (pthread_equal((*((struct_thread *)                  == getpid()) && (pthread_equal((*((struct_thread *)
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
             if (pthread_mutex_lock(&((*(*((struct_thread *) (*l_element_courant)  #           ifndef SEMAPHORES_NOMMES
                     .donnee)).s_etat_processus).mutex_fork)) == -1)                  while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)
                           .donnee)).s_etat_processus).semaphore_fork)) == -1)
   #           else
                   while(sem_wait((*(*((struct_thread *) (*l_element_courant)
                           .donnee)).s_etat_processus).semaphore_fork) == -1)
   #           endif
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 return;                  return;
Line 351  deverrouillage_threads_concurrents(struc Line 516  deverrouillage_threads_concurrents(struc
                 == getpid()) && (pthread_equal((*((struct_thread *)                  == getpid()) && (pthread_equal((*((struct_thread *)
                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))                  (*l_element_courant).donnee)).tid, pthread_self()) == 0))
         {          {
             if (pthread_mutex_unlock(&((*(*((struct_thread *)  #           ifndef SEMAPHORES_NOMMES
                     (*l_element_courant).donnee)).s_etat_processus)                  if (sem_post(&((*(*((struct_thread *)
                     .mutex_fork)) != 0)                          (*l_element_courant).donnee)).s_etat_processus)
                           .semaphore_fork)) != 0)
   #           else
                   if (sem_post((*(*((struct_thread *)
                           (*l_element_courant).donnee)).s_etat_processus)
                           .semaphore_fork) != 0)
   #           endif
             {              {
                 if (pthread_mutex_unlock(&mutex_liste_threads) != 0)                  if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
                 {                  {
Line 387  liberation_threads(struct_processus *s_e Line 558  liberation_threads(struct_processus *s_e
   
     struct_processus                            *candidat;      struct_processus                            *candidat;
   
     unsigned long                               i;      struct_liste_variables_partagees            *l_element_partage_courant;
       struct_liste_variables_partagees            *l_element_partage_suivant;
   
       struct_liste_variables_statiques            *l_element_statique_courant;
       struct_liste_variables_statiques            *l_element_statique_suivant;
   
       integer8                                    i;
   
     void                                        *element_candidat;      void                                        *element_candidat;
     void                                        *element_courant;      void                                        *element_courant;
Line 430  liberation_threads(struct_processus *s_e Line 607  liberation_threads(struct_processus *s_e
             close((*s_etat_processus).pipe_injections);              close((*s_etat_processus).pipe_injections);
             close((*s_etat_processus).pipe_nombre_injections);              close((*s_etat_processus).pipe_nombre_injections);
             close((*s_etat_processus).pipe_interruptions);              close((*s_etat_processus).pipe_interruptions);
             close((*s_etat_processus).pipe_nombre_objets_attente);              close((*s_etat_processus).pipe_nombre_elements_attente);
             close((*s_etat_processus).pipe_nombre_interruptions_attente);  
   
             liberation(s_etat_processus, (*s_etat_processus).at_exit);              liberation(s_etat_processus, (*s_etat_processus).at_exit);
   
Line 499  liberation_threads(struct_processus *s_e Line 675  liberation_threads(struct_processus *s_e
                     close((*s_argument_thread).pipe_acquittement[1]);                      close((*s_argument_thread).pipe_acquittement[1]);
                     close((*s_argument_thread).pipe_injections[1]);                      close((*s_argument_thread).pipe_injections[1]);
                     close((*s_argument_thread).pipe_nombre_injections[1]);                      close((*s_argument_thread).pipe_nombre_injections[1]);
                     close((*s_argument_thread).pipe_nombre_objets_attente[0]);                      close((*s_argument_thread).pipe_nombre_elements_attente[0]);
                     close((*s_argument_thread).pipe_interruptions[0]);                      close((*s_argument_thread).pipe_interruptions[0]);
                     close((*s_argument_thread)  
                             .pipe_nombre_interruptions_attente[0]);  
   
                     if (pthread_mutex_unlock(&((*s_argument_thread)                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             .mutex_nombre_references)) != 0)                              .mutex_nombre_references)) != 0)
Line 602  liberation_threads(struct_processus *s_e Line 776  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             liberation_arbre_variables(s_etat_processus,  
                     (*s_etat_processus).s_arbre_variables, d_faux);  
   
             for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)  
             {  
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet).mutex));  
   
                 liberation(s_etat_processus, (*s_etat_processus)  
                         .s_liste_variables_statiques[i].objet);  
                 free((*s_etat_processus).s_liste_variables_statiques[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables_statiques);  
   
             // Ne peut être effacé qu'une seule fois              // Ne peut être effacé qu'une seule fois
             if (suppression_variables_partagees == d_faux)              if (suppression_variables_partagees == d_faux)
             {              {
                 suppression_variables_partagees = d_vrai;                  suppression_variables_partagees = d_vrai;
   
                 for(i = 0; i < (*(*s_etat_processus)                  liberation_arbre_variables_partagees(s_etat_processus,
                         .s_liste_variables_partagees).nombre_variables; i++)                          (*(*s_etat_processus).s_arbre_variables_partagees));
                 {                  (*(*s_etat_processus).s_arbre_variables_partagees) = NULL;
                     pthread_mutex_trylock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
                     pthread_mutex_unlock(&((*(*(*s_etat_processus)  
                             .s_liste_variables_partagees).table[i].objet)  
                             .mutex));  
   
                     liberation(s_etat_processus, (*(*s_etat_processus)                  l_element_partage_courant = (*(*s_etat_processus)
                             .s_liste_variables_partagees).table[i].objet);                          .l_liste_variables_partagees);
                     free((*(*s_etat_processus).s_liste_variables_partagees)  
                             .table[i].nom);  
                 }  
   
                 if ((*(*s_etat_processus).s_liste_variables_partagees).table                  while(l_element_partage_courant != NULL)
                         != NULL)  
                 {                  {
                     free((struct_variable_partagee *) (*(*s_etat_processus)                      l_element_partage_suivant =
                             .s_liste_variables_partagees).table);                              (*l_element_partage_courant).suivant;
                       free(l_element_partage_courant);
                       l_element_partage_courant = l_element_partage_suivant;
                 }                  }
   
                 pthread_mutex_trylock(&((*(*s_etat_processus)                  (*(*s_etat_processus).l_liste_variables_partagees) = NULL;
                         .s_liste_variables_partagees).mutex));              }
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables_partagees).mutex));              liberation_arbre_variables(s_etat_processus,
                       (*s_etat_processus).s_arbre_variables, d_faux);
   
               l_element_statique_courant = (*s_etat_processus)
                       .l_liste_variables_statiques;
   
               while(l_element_statique_courant != NULL)
               {
                   l_element_statique_suivant =
                       (*l_element_statique_courant).suivant;
                   free(l_element_statique_courant);
                   l_element_statique_courant = l_element_statique_suivant;
             }              }
   
             element_courant = (*s_etat_processus).l_base_pile;              element_courant = (*s_etat_processus).l_base_pile;
Line 1109  liberation_threads(struct_processus *s_e Line 1269  liberation_threads(struct_processus *s_e
   
             liberation_allocateur(s_etat_processus);              liberation_allocateur(s_etat_processus);
   
             pthread_mutex_unlock(&((*s_etat_processus).mutex_fork));  #           ifndef SEMAPHORES_NOMMES
             pthread_mutex_destroy(&((*s_etat_processus).mutex_fork));                  sem_post(&((*s_etat_processus).semaphore_fork));
                   sem_destroy(&((*s_etat_processus).semaphore_fork));
   #           else
                   sem_post((*s_etat_processus).semaphore_fork);
                   sem_close((*s_etat_processus).semaphore_fork);
   #           endif
   
             liberation_contexte_cas(s_etat_processus);              liberation_contexte_cas(s_etat_processus);
             free(s_etat_processus);              liberation_allocateur_buffer(s_etat_processus);
               sys_free(s_etat_processus);
   
             s_etat_processus = candidat;              s_etat_processus = candidat;
         }          }
Line 1155  liberation_threads(struct_processus *s_e Line 1321  liberation_threads(struct_processus *s_e
             close((*s_argument_thread).pipe_acquittement[1]);              close((*s_argument_thread).pipe_acquittement[1]);
             close((*s_argument_thread).pipe_injections[1]);              close((*s_argument_thread).pipe_injections[1]);
             close((*s_argument_thread).pipe_nombre_injections[1]);              close((*s_argument_thread).pipe_nombre_injections[1]);
             close((*s_argument_thread).pipe_nombre_objets_attente[0]);              close((*s_argument_thread).pipe_nombre_elements_attente[0]);
             close((*s_argument_thread).pipe_interruptions[0]);              close((*s_argument_thread).pipe_interruptions[0]);
             close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);  
   
             if (pthread_mutex_unlock(&((*s_argument_thread)              if (pthread_mutex_unlock(&((*s_argument_thread)
                     .mutex_nombre_references)) != 0)                      .mutex_nombre_references)) != 0)
Line 1215  recherche_thread(pid_t pid, pthread_t ti Line 1380  recherche_thread(pid_t pid, pthread_t ti
   
     struct_processus                            *s_etat_processus;      struct_processus                            *s_etat_processus;
   
       if (pthread_mutex_lock(&mutex_liste_threads) != 0)
       {
           return(NULL);
       }
   
     l_element_courant = liste_threads;      l_element_courant = liste_threads;
   
     while(l_element_courant != NULL)      while(l_element_courant != NULL)
Line 1235  recherche_thread(pid_t pid, pthread_t ti Line 1405  recherche_thread(pid_t pid, pthread_t ti
          * Le processus n'existe plus. On ne distribue aucun signal.           * Le processus n'existe plus. On ne distribue aucun signal.
          */           */
   
           pthread_mutex_unlock(&mutex_liste_threads);
         return(NULL);          return(NULL);
     }      }
   
     s_etat_processus = (*((struct_thread *)      s_etat_processus = (*((struct_thread *)
             (*l_element_courant).donnee)).s_etat_processus;              (*l_element_courant).donnee)).s_etat_processus;
   
       if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
       {
           return(NULL);
       }
   
     return(s_etat_processus);      return(s_etat_processus);
 }  }
   
Line 1296  recherche_thread_principal(pid_t pid) Line 1472  recherche_thread_principal(pid_t pid)
 static inline void  static inline void
 verrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)  verrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 {  {
     int         semaphore;  
   
     if (pthread_mutex_unlock(&((*s_etat_processus).mutex_fork)) != 0)  
     {  
         BUG(1, uprintf("Lock error !\n"));  
         return;  
     }  
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !  
   
     if (pthread_mutex_lock(&mutex_gestionnaires_signaux_atomique) != 0)  
     {  
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));  
         BUG(1, uprintf("Unlock error !\n"));  
         return;  
     }  
   
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
     if (sem_post(&semaphore_gestionnaires_signaux) == -1)      if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
 #   else  #   else
     if (sem_post(semaphore_gestionnaires_signaux) == -1)      if (sem_post((*s_etat_processus).semaphore_fork) != 0)
 #   endif  #   endif
     {      {
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));  
         BUG(1, uprintf("Lock error !\n"));          BUG(1, uprintf("Lock error !\n"));
         return;          return;
     }      }
   
       return;
   }
   
   static inline void
   deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
   {
 #   ifndef SEMAPHORES_NOMMES  #   ifndef SEMAPHORES_NOMMES
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)      while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
 #   else  #   else
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)      while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
 #   endif  #   endif
     {      {
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));          if (errno != EINTR)
         BUG(1, uprintf("Lock error !\n"));  
         return;  
     }  
   
     if (pthread_mutex_unlock(&mutex_gestionnaires_signaux_atomique) != 0)  
     {  
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));  
         BUG(1, uprintf("Unlock error !\n"));  
         return;  
     }  
   
     if (semaphore == 1)  
     {  
         // Le semaphore ne peut être pris par le thread qui a appelé  
         // le gestionnaire de signal car le signal est bloqué par ce thread  
         // dans les zones critiques. Ce sémaphore ne peut donc être bloqué que  
         // par un thread concurrent. On essaye donc de le bloquer jusqu'à  
         // ce que ce soit possible.  
   
         if (pthread_mutex_lock(&mutex_liste_threads) != 0)  
         {          {
             pthread_mutex_lock(&((*s_etat_processus).mutex_fork));              BUG(1, uprintf("Unlock error !\n"));
             BUG(1, uprintf("Lock error !\n"));  
             return;              return;
         }          }
     }      }
Line 1361  verrouillage_gestionnaire_signaux(struct Line 1504  verrouillage_gestionnaire_signaux(struct
     return;      return;
 }  }
   
 static inline void  /*
 deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)  ================================================================================
 {    Fonctions de gestion des signaux dans les threads.
     int         semaphore;  
   
     // Il faut respecteur l'atomicité des deux opérations suivantes !    Lorsqu'un processus reçoit un signal, il appelle le gestionnaire de signal
     associé qui ne fait qu'envoyer au travers de write() le signal
     reçus dans un pipe. Un second thread est bloqué sur ce pipe et
     effectue le traitement adéquat pour le signal donné.
   ================================================================================
   */
   
   #define test_signal(signal) \
       if (signal_test == SIGTEST) { signal_test = signal; return; }
   
   static int          pipe_signaux;
   
   logical1
   lancement_thread_signaux(struct_processus *s_etat_processus)
   {
       pthread_attr_t                  attributs;
   
     if (pthread_mutex_lock(&mutex_gestionnaires_signaux_atomique) == -1)      if (pipe((*s_etat_processus).pipe_signaux) != 0)
     {      {
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Unlock error !\n"));          return(d_erreur);
         return;  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      pipe_signaux = (*s_etat_processus).pipe_signaux[1];
     if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   else      if (pthread_attr_init(&attributs) != 0)
     if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)  
 #   endif  
     {      {
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Unlock error !\n"));          return(d_erreur);
         return;  
     }      }
   
 #   ifndef SEMAPHORES_NOMMES      if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
     while(sem_wait(&semaphore_gestionnaires_signaux) == -1)  
 #   else  
     while(sem_wait(semaphore_gestionnaires_signaux) == -1)  
 #   endif  
     {      {
         if (errno != EINTR)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {          return(d_erreur);
             pthread_mutex_lock(&((*s_etat_processus).mutex_fork));  
             BUG(1, uprintf("Unlock error !\n"));  
             return;  
         }  
     }      }
   
     if (pthread_mutex_unlock(&mutex_gestionnaires_signaux_atomique) != 0)      if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
               thread_signaux, s_etat_processus) != 0)
     {      {
         pthread_mutex_lock(&((*s_etat_processus).mutex_fork));          (*s_etat_processus).erreur_systeme = d_es_processus;
         BUG(1, uprintf("Unlock error !\n"));          return(d_erreur);
         return;  
     }      }
   
     if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)      if (pthread_attr_destroy(&attributs) != 0)
     {      {
         BUG(1, uprintf("Unlock error !\n"));          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return(d_erreur);
     }      }
   
     if (semaphore == 1)      return(d_absence_erreur);
   }
   
   logical1
   arret_thread_signaux(struct_processus *s_etat_processus)
   {
       unsigned char       signal;
       ssize_t             n;
   
       signal = (unsigned char ) (rpl_sigmax & 0xFF);
   
       do
     {      {
         if (pthread_mutex_unlock(&mutex_liste_threads) != 0)          n = write_atomic(s_etat_processus, (*s_etat_processus).pipe_signaux[1],
                   &signal, sizeof(signal));
   
           if (n < 0)
         {          {
             BUG(1, uprintf("Unlock error !\n"));              return(d_erreur);
             return;          }
       } while(n != 1);
   
       pthread_join((*s_etat_processus).thread_signaux, NULL);
   
       close((*s_etat_processus).pipe_signaux[1]);
       return(d_absence_erreur);
   }
   
   void *
   thread_signaux(void *argument)
   {
       int                     *pipe;
   
       sigset_t                masque;
   
       struct pollfd           fds;
   
       struct_processus        *s_etat_processus;
   
       unsigned char           signal;
   
       s_etat_processus = (struct_processus *) argument;
       pipe = (*s_etat_processus).pipe_signaux;
       fds.fd = pipe[0];
       fds.events = POLLIN;
   
       sigfillset(&masque);
       pthread_sigmask(SIG_BLOCK, &masque, NULL);
   
       do
       {
           fds.revents = 0;
   
           while(poll(&fds, 1, -1) == -1)
           {
               if (errno != EINTR)
               {
                   close((*s_etat_processus).pipe_signaux[0]);
                   pthread_exit(NULL);
               }
           }
   
           if (read_atomic(s_etat_processus, fds.fd, &signal, 1) != 1)
           {
               close((*s_etat_processus).pipe_signaux[0]);
               pthread_exit(NULL);
           }
   
           if (signal != (0xFF & rpl_sigmax))
           {
               envoi_signal_processus(getpid(), signal, d_faux);
               // Un signal SIGUSR2 est envoyé par le thread de surveillance
               // des signaux jusqu'à ce que les signaux soient tous traités.
           }
       } while(signal != (0xFF & rpl_sigmax));
   
       close((*s_etat_processus).pipe_signaux[0]);
       pthread_exit(NULL);
   }
   
   
   static inline void
   _write(int fd, const void *buf, size_t count)
   {
       ssize_t         ios;
   
       while((ios = write(fd, buf, count)) == -1)
       {
           if (errno != EINTR)
           {
               break;
         }          }
     }      }
   
     return;      return;
 }  }
   
 #define test_signal(signal) \  
     if (signal_test == SIGTEST) { signal_test = signal; return; }  
   
 // Récupération des signaux  // Récupération des signaux
 // - SIGINT (arrêt au clavier)  // - SIGINT  (arrêt au clavier)
 // - SIGTERM (signal d'arrêt en provenance du système)  // - SIGTERM (signal d'arrêt en provenance du système)
   
 void  void
 interruption1(int signal)  interruption1(int signal)
 {  {
       unsigned char       signal_tronque;
   
     test_signal(signal);      test_signal(signal);
   
     switch(signal)      switch(signal)
     {      {
         case SIGINT:          case SIGINT:
             envoi_signal_processus(getpid(), rpl_sigint);              signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             break;              break;
   
         case SIGTERM:          case SIGTERM:
             envoi_signal_processus(getpid(), rpl_sigterm);              signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
               break;
   
           case SIGUSR1:
               signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
               _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
             break;              break;
   
         case SIGALRM:          default:
             envoi_signal_processus(getpid(), rpl_sigalrm);              // SIGUSR2
             break;              break;
     }      }
   
     return;      return;
 }  }
   
   // Récupération des signaux
   // - SIGFSTP
   //
   // ATTENTION :
   // Le signal SIGFSTP provient de la mort du processus de contrôle.
   // Sous certains systèmes (Linux...), la mort du terminal de contrôle
   // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
   // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
   // non initialisée (pointeur NULL) issue de TERMIO.
   
   void
   interruption2(int signal)
   {
       unsigned char       signal_tronque;
   
       test_signal(signal);
   
       signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
       _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
   
       return;
   }
   
   void
   interruption3(int signal)
   {
       // Si on passe par ici, c'est qu'il est impossible de récupérer
       // l'erreur d'accès à la mémoire. On sort donc du programme quitte à
       // ce qu'il reste des processus orphelins.
   
       unsigned char       message_1[] = "+++System : Uncaught access violation\n"
                                   "+++System : Aborting !\n";
       unsigned char       message_2[] = "+++System : Stack overflow\n"
                                   "+++System : Aborting !\n";
   
       test_signal(signal);
   
       if (pid_processus_pere == getpid())
       {
           kill(pid_processus_pere, SIGUSR1);
       }
   
   #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
       if (signal != SIGUSR2)
       {
           write(STDERR_FILENO, message_1, strlen(message_1));
       }
       else
       {
           write(STDERR_FILENO, message_2, strlen(message_2));
       }
   
   #   pragma GCC diagnostic pop
   
       _exit(EXIT_FAILURE);
   }
   
   // Récupération des signaux
   // - SIGHUP
   
   void
   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;
   }
   
   // Récupération des signaux
   // - SIGPIPE
   
   void
   interruption5(int signal)
   {
       unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
       unsigned char       signal_tronque;
   
       test_signal(signal);
   
   #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
       if (pid_processus_pere == getpid())
       {
           signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
           _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
       }
   
       write(STDERR_FILENO, message, strlen(message));
   
   #   pragma GCC diagnostic pop
   
       return;
   }
   
 inline static void  inline static void
 signal_alrm(struct_processus *s_etat_processus, pid_t pid)  signal_alrm(struct_processus *s_etat_processus, pid_t pid)
 {  {
Line 1479  signal_alrm(struct_processus *s_etat_pro Line 1819  signal_alrm(struct_processus *s_etat_pro
         {          {
             // On n'est pas dans le processus père, on remonte le signal.              // On n'est pas dans le processus père, on remonte le signal.
             envoi_signal_processus((*s_etat_processus).pid_processus_pere,              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                     rpl_sigalrm);                      rpl_sigalrm, d_faux);
         }          }
         else          else
         {          {
Line 1508  inline static void Line 1848  inline static void
 signal_term(struct_processus *s_etat_processus, pid_t pid)  signal_term(struct_processus *s_etat_processus, pid_t pid)
 {  {
     struct_processus        *s_thread_principal;      struct_processus        *s_thread_principal;
     volatile sig_atomic_t   exclusion = 0;      pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
   
     verrouillage_gestionnaire_signaux(s_etat_processus);      verrouillage_gestionnaire_signaux(s_etat_processus);
   
Line 1524  signal_term(struct_processus *s_etat_pro Line 1864  signal_term(struct_processus *s_etat_pro
         if ((*s_etat_processus).pid_processus_pere != getpid())          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             envoi_signal_processus((*s_etat_processus).pid_processus_pere,              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                     rpl_sigterm);                      rpl_sigterm, d_faux);
         }          }
         else          else
         {          {
             (*s_etat_processus).var_volatile_traitement_sigint = -1;              (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
             while(exclusion == 1);              pthread_mutex_lock(&exclusion);
             exclusion = 1;  
   
             if ((*s_etat_processus).var_volatile_requete_arret == -1)              if ((*s_etat_processus).var_volatile_requete_arret == -1)
             {              {
                 deverrouillage_gestionnaire_signaux(s_etat_processus);                  deverrouillage_gestionnaire_signaux(s_etat_processus);
                 exclusion = 0;                  pthread_mutex_unlock(&exclusion);
                 return;                  return;
             }              }
   
             (*s_etat_processus).var_volatile_requete_arret = -1;              (*s_etat_processus).var_volatile_requete_arret = -1;
             (*s_etat_processus).var_volatile_alarme = -1;              (*s_etat_processus).var_volatile_alarme = -1;
   
             exclusion = 0;              pthread_mutex_unlock(&exclusion);
         }          }
     }      }
     else      else
Line 1579  signal_int(struct_processus *s_etat_proc Line 1918  signal_int(struct_processus *s_etat_proc
         if ((*s_etat_processus).pid_processus_pere != getpid())          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             envoi_signal_processus((*s_etat_processus).pid_processus_pere,              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                     rpl_sigint);                      rpl_sigint, d_faux);
         }          }
         else          else
         {          {
Line 1625  signal_int(struct_processus *s_etat_proc Line 1964  signal_int(struct_processus *s_etat_proc
     return;      return;
 }  }
   
 // Récupération des signaux  
 // - SIGFSTP  
 //  
 // ATTENTION :  
 // Le signal SIGFSTP provient de la mort du processus de contrôle.  
 // Sous certains systèmes (Linux...), la mort du terminal de contrôle  
 // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres  
 // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo  
 // non initialisée (pointeur NULL) issue de TERMIO.  
   
 void  
 interruption2(int signal)  
 {  
     test_signal(signal);  
     envoi_signal_processus(getpid(), rpl_sigtstp);  
     return;  
 }  
   
 static inline void  static inline void
 signal_tstp(struct_processus *s_etat_processus, pid_t pid)  signal_tstp(struct_processus *s_etat_processus, pid_t pid)
 {  {
Line 1668  signal_tstp(struct_processus *s_etat_pro Line 1989  signal_tstp(struct_processus *s_etat_pro
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          if ((*s_etat_processus).var_volatile_processus_pere == 0)
         {          {
             envoi_signal_processus((*s_etat_processus).pid_processus_pere,              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                     rpl_sigtstp);                      rpl_sigtstp, d_faux);
         }          }
         else          else
         {          {
Line 1690  signal_tstp(struct_processus *s_etat_pro Line 2011  signal_tstp(struct_processus *s_etat_pro
     return;      return;
 }  }
   
 void  static void
 interruption3(int signal)  sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
 {  {
     // Si on passe par ici, c'est qu'il est impossible de récupérer      switch((*((volatile int *) arg1)))
     // l'erreur d'accès à la mémoire. On sort donc du programme quitte à  
     // ce qu'il reste des processus orphelins.  
   
     unsigned char       message[] = "+++System : Uncaught access violation\n"  
                                 "+++System : Aborting !\n";  
   
     test_signal(signal);  
   
     if (pid_processus_pere == getpid())  
     {      {
         kill(pid_processus_pere, SIGALRM);          case 1:
               longjmp(contexte_ecriture, -1);
               break;
   
           case 2:
               longjmp(contexte_impression, -1);
               break;
     }      }
   
     write(STDERR_FILENO, message, strlen(message));      return;
     _exit(EXIT_FAILURE);  
 }  }
   
 #if 0  #ifdef HAVE_SIGSEGV_RECOVERY
 // Utiliser libsigsegv  void
 void INTERRUPTION3_A_FIXER()  interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
 {  {
     pthread_t               thread;      if ((urgence == 0) && (routine_recursive != 0))
   
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  
     verrouillage_gestionnaire_signaux(s_etat_processus);  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  
     {      {
         deverrouillage_gestionnaire_signaux(s_etat_processus);          // On peut tenter de récupérer le dépassement de pile. Si la variable
         return;          // 'routine_recursive' est non nulle, on récupère l'erreur.
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          sigsegv_leave_handler(sortie_interruption_depassement_pile,
     {                  (void *) &routine_recursive, NULL, NULL);
         printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   
     if ((*s_etat_processus).var_volatile_recursivite == -1)      // Ici, la panique est totale et il vaut mieux quitter l'application.
     {      interruption3(SIGUSR2);
         // Segfault dans un appel de fonction récursive      return;
         deverrouillage_gestionnaire_signaux(s_etat_processus);  }
         longjmp(contexte, -1);  #endif
     }  
     else  
     {  
         // Segfault dans une routine interne  
         if (strncmp(getenv("LANG"), "fr", 2) == 0)  
         {  
             printf("+++Système : Violation d'accès\n");  
         }  
         else  
         {  
             printf("+++System : Access violation\n");  
         }  
   
         fflush(stdout);  
   
         (*s_etat_processus).compteur_violation_d_acces++;  
   
         if ((*s_etat_processus).compteur_violation_d_acces > 1)  int
         {  interruption_violation_access(void *adresse_fautive, int gravite)
             // On vient de récupérer plus d'une erreur de segmentation  {
             // dans le même processus ou le même thread. L'erreur n'est pas      unsigned char       message[] = "+++System : Trying to catch access "
             // récupérable et on sort autoritairement du programme. Il peut                                  "violation\n";
             // rester des processus orphelins en attente !  
   
             if (strncmp(getenv("LANG"), "fr", 2) == 0)      static int          compteur_erreur = 0;
             {  
                 printf("+++Système : Violation d'accès, tentative de "  
                         "terminaison de la tâche\n");  
                 printf("             (defauts multiples)\n");  
             }  
             else  
             {  
                 printf("+++System : Access violation, trying to kill task "  
                         "(multiple defaults)\n");  
             }  
   
             fflush(stdout);      if ((gravite == 0) && (routine_recursive != 0))
       {
           // Il peut s'agir d'un dépassement de pile.
   
             deverrouillage_gestionnaire_signaux(s_etat_processus);  #       ifdef HAVE_SIGSEGV_RECOVERY
             exit(EXIT_FAILURE);              sigsegv_leave_handler(sortie_interruption_depassement_pile,
         }                      (void *) &routine_recursive, NULL, NULL);
         else  #       else
         {              sortie_interruption_depassement_pile((void *) &routine_recursive,
             // Première erreur de segmentation. On essaie de terminer                      NULL, NULL);
             // proprement le thread ou le processus. Le signal ne peut être  #       endif
             // envoyé que depuis le même processus.      }
   
             if (recherche_thread_principal(getpid(), &thread) == d_vrai)      // On est dans une bonne vieille violation d'accès. On essaie
             {      // de fermer au mieux l'application.
                 if (pthread_equal(thread, pthread_self()) != 0)  
                 {  
                     deverrouillage_gestionnaire_signaux(s_etat_processus);  
   
                     if ((*s_etat_processus).pid_processus_pere != getpid())      compteur_erreur++;
                     {  
                         // On est dans le thread principal d'un processus.  
   
                         longjmp(contexte_processus, -1);      if (compteur_erreur >= 2)
                     }      {
                     else          // Erreurs multiples, on arrête l'application.
                     {          interruption3(SIGSEGV);
                         // On est dans le thread principal du processus          return(0);
                         // père.      }
   
                         longjmp(contexte_initial, -1);  #   pragma GCC diagnostic push
                     }  #   pragma GCC diagnostic ignored "-Wunused-result"
                 }  
                 else  
                 {  
                     // On est dans un thread fils d'un thread principal.  
   
                     deverrouillage_gestionnaire_signaux(s_etat_processus);      write(STDERR_FILENO, message, strlen(message));
                     longjmp(contexte_thread, -1);  
                 }  
             }  
   
             // Là, on ramasse les miettes puisque le thread n'existe plus  #   pragma GCC diagnostic pop
             // dans la base (corruption de la mémoire).  
   
             deverrouillage_gestionnaire_signaux(s_etat_processus);      if (pid_processus_pere == getpid())
             longjmp(contexte_initial, -1);      {
         }          longjmp(contexte_initial, -1);
           return(1);
       }
       else
       {
           longjmp(contexte_processus, -1);
           return(1);
     }      }
   
     deverrouillage_gestionnaire_signaux(s_etat_processus);      // On renvoie 0 parce qu'on décline toute responsabilité quant à la
     return;      // suite des événements...
       return(0);
 }  }
 #endif  
   
 // Traitement de rpl_sigstart  // Traitement de rpl_sigstart
   
Line 1896  signal_stop(struct_processus *s_etat_pro Line 2170  signal_stop(struct_processus *s_etat_pro
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux(s_etat_processus);  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
Line 1965  signal_inject(struct_processus *s_etat_p Line 2232  signal_inject(struct_processus *s_etat_p
     return;      return;
 }  }
   
 // Récupération des signaux  
 // - SIGPIPE  
   
 void  
 interruption5(int signal)  
 {  
     unsigned char       message[] = "+++System : SIGPIPE\n"  
                                 "+++System : Aborting !\n";  
   
     test_signal(signal);  
   
     if (pid_processus_pere == getpid())  
     {  
         envoi_signal_processus(pid_processus_pere, rpl_sigalrm);  
     }  
   
     write(STDERR_FILENO, message, strlen(message));  
     return;  
 }  
   
 static inline void  static inline void
 signal_urg(struct_processus *s_etat_processus, pid_t pid)  signal_urg(struct_processus *s_etat_processus, pid_t pid)
Line 1994  signal_urg(struct_processus *s_etat_proc Line 2242  signal_urg(struct_processus *s_etat_proc
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux(s_etat_processus);  
             return;  
         }  
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
Line 2050  signal_abort(struct_processus *s_etat_pr Line 2291  signal_abort(struct_processus *s_etat_pr
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux(s_etat_processus);  
             return;  
         }  
   
         (*s_etat_processus).arret_depuis_abort = -1;          (*s_etat_processus).arret_depuis_abort = -1;
   
         /*          /*
Line 2092  signal_abort(struct_processus *s_etat_pr Line 2326  signal_abort(struct_processus *s_etat_pr
     return;      return;
 }  }
   
 // Récupération des signaux  
 // - SIGHUP  
   
 void  
 interruption4(int signal)  
 {  
     test_signal(signal);  
     envoi_signal_processus(getpid(), rpl_sighup);  
     return;  
 }  
   
 static inline void  static inline void
 signal_hup(struct_processus *s_etat_processus, pid_t pid)  signal_hup(struct_processus *s_etat_processus, pid_t pid)
Line 2118  signal_hup(struct_processus *s_etat_proc Line 2342  signal_hup(struct_processus *s_etat_proc
         return;          return;
     }      }
   
     snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),      snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
             (unsigned long) pthread_self());              (unsigned long long) getpid(),
               (unsigned long long) pthread_self());
   
   #   pragma GCC diagnostic push
   #   pragma GCC diagnostic ignored "-Wunused-result"
   
     if ((fichier = fopen(nom, "w+")) != NULL)      if ((fichier = fopen(nom, "w+")) != NULL)
     {      {
Line 2131  signal_hup(struct_processus *s_etat_proc Line 2359  signal_hup(struct_processus *s_etat_proc
   
     freopen("/dev/null", "r", stdin);      freopen("/dev/null", "r", stdin);
   
   #   pragma GCC diagnostic pop
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
Line 2147  traitement_exceptions_gsl(const char *re Line 2377  traitement_exceptions_gsl(const char *re
         int line, int gsl_errno)          int line, int gsl_errno)
 {  {
     code_erreur_gsl = gsl_errno;      code_erreur_gsl = gsl_errno;
     envoi_signal_processus(getpid(), rpl_sigexcept);      envoi_signal_processus(getpid(), rpl_sigexcept, d_faux);
     return;      return;
 }  }
   
Line 2172  static inline void Line 2402  static inline void
 envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,  envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
         pid_t pid_source)          pid_t pid_source)
 {  {
 uprintf("Signal : %d\n", signal);  
     switch(signal)      switch(signal)
     {      {
         case rpl_signull:          case rpl_signull:
Line 2229  uprintf("Signal : %d\n", signal); Line 2458  uprintf("Signal : %d\n", signal);
         default:          default:
             if ((*s_etat_processus).langue == 'F')              if ((*s_etat_processus).langue == 'F')
             {              {
                 printf("+++System : Spurious signal (%d) !\n", signal);                  printf("+++System : Signal inconnu (%d) !\n", signal);
             }              }
             else              else
             {              {
                 printf("+++System : Signal inconnu (%d) !\n", signal);                  printf("+++System : Spurious signal (%d) !\n", signal);
             }              }
   
             break;              break;
Line 2252  scrutation_interruptions(struct_processu Line 2481  scrutation_interruptions(struct_processu
     // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à      // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
     // écrire.      // écrire.
   
     if (pthread_mutex_trylock(&((*s_queue_signaux).mutex)) == 0)      if (sem_trywait(semaphore_queue_signaux) == 0)
     {      {
         if ((*s_queue_signaux).pointeur_lecture !=          while((*s_queue_signaux).pointeur_lecture !=
                 (*s_queue_signaux).pointeur_ecriture)                  (*s_queue_signaux).pointeur_ecriture)
         {          {
             // Il y a un signal en attente dans le segment partagé. On le              // Il y a un signal en attente dans le segment partagé. On le
Line 2267  scrutation_interruptions(struct_processu Line 2496  scrutation_interruptions(struct_processu
             (*s_queue_signaux).pointeur_lecture =              (*s_queue_signaux).pointeur_lecture =
                     ((*s_queue_signaux).pointeur_lecture + 1)                      ((*s_queue_signaux).pointeur_lecture + 1)
                     % LONGUEUR_QUEUE_SIGNAUX;                      % LONGUEUR_QUEUE_SIGNAUX;
 uprintf("Traité\n");  
   #           ifndef IPCS_SYSV
               if (msync(s_queue_signaux, sizeof(s_queue_signaux),
                       MS_ASYNC | MS_INVALIDATE) != 0)
               {
                   sem_post(semaphore_queue_signaux);
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   #           endif
   
               while(sem_wait(semaphore_signalisation) != 0)
               {
                   if (errno != EINTR)
                   {
                       (*s_etat_processus).erreur_systeme = d_es_processus;
                       return;
                   }
               }
         }          }
   
         pthread_mutex_unlock(&((*s_queue_signaux).mutex));          sem_post(semaphore_queue_signaux);
     }      }
   
     // Interruptions qui arrivent depuis le groupe courant de threads.      // Interruptions qui arrivent depuis le groupe courant de threads.
   
     if (pthread_mutex_trylock(&mutex_interruptions) == 0)      if (pthread_mutex_trylock(&mutex_liste_threads) == 0)
     {      {
         if ((*s_etat_processus).pointeur_signal_lecture !=          if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
                 (*s_etat_processus).pointeur_signal_ecriture)  
         {          {
             // Il y a un signal dans la queue du thread courant. On le traite.              while((*s_etat_processus).pointeur_signal_lecture !=
                       (*s_etat_processus).pointeur_signal_ecriture)
               {
                   // Il y a un signal dans la queue du thread courant.
                   // On le traite.
   
             envoi_interruptions(s_etat_processus,                  envoi_interruptions(s_etat_processus,
                     (*s_etat_processus).signaux_en_queue                          (*s_etat_processus).signaux_en_queue
                     [(*s_etat_processus).pointeur_signal_lecture],                          [(*s_etat_processus).pointeur_signal_lecture],
                     getpid());                          getpid());
             (*s_etat_processus).pointeur_signal_lecture =                  (*s_etat_processus).pointeur_signal_lecture =
                     ((*s_etat_processus).pointeur_signal_lecture + 1)                          ((*s_etat_processus).pointeur_signal_lecture + 1)
                     % LONGUEUR_QUEUE_SIGNAUX;                          % LONGUEUR_QUEUE_SIGNAUX;
   
                   while(sem_wait(semaphore_signalisation) != 0)
                   {
                       if (errno != EINTR)
                       {
                           if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
                           {
                               (*s_etat_processus).erreur_systeme = d_es_processus;
                               return;
                           }
   
                           (*s_etat_processus).erreur_systeme = d_es_processus;
                           return;
                       }
                   }
               }
   
               pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
         }          }
   
         pthread_mutex_unlock(&mutex_interruptions);          pthread_mutex_unlock(&mutex_liste_threads);
     }      }
   
     return;      return;
 }  }
   
   
 /*  /*
 ================================================================================  ================================================================================
   Fonction renvoyant le nom du segment de mémoire partagée en fonction    Fonction renvoyant le nom du segment de mémoire partagée en fonction
Line 2318  nom_segment(unsigned char *chemin, pid_t Line 2587  nom_segment(unsigned char *chemin, pid_t
 #   ifdef IPCS_SYSV // !POSIX  #   ifdef IPCS_SYSV // !POSIX
 #       ifndef OS2 // !OS2  #       ifndef OS2 // !OS2
   
             if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *              if ((fichier = sys_malloc((strlen(chemin) + 1 + 256 + 1) *
                     sizeof(unsigned char))) == NULL)                      sizeof(unsigned char))) == NULL)
             {              {
                 return(NULL);                  return(NULL);
Line 2326  nom_segment(unsigned char *chemin, pid_t Line 2595  nom_segment(unsigned char *chemin, pid_t
   
             sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);              sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
 #       else // OS2  #       else // OS2
             if ((fichier = malloc((10 + 256 + 1) * sizeof(unsigned char)))              if ((fichier = sys_malloc((10 + 256 + 1) * sizeof(unsigned char)))
                     == NULL)                      == NULL)
             {              {
                 return(NULL);                  return(NULL);
Line 2336  nom_segment(unsigned char *chemin, pid_t Line 2605  nom_segment(unsigned char *chemin, pid_t
 #       endif // OS2  #       endif // OS2
 #   else // POSIX  #   else // POSIX
   
         if ((fichier = malloc((1 + 256 + 1) *          if ((fichier = sys_malloc((1 + 256 + 1) *
                 sizeof(unsigned char))) == NULL)                  sizeof(unsigned char))) == NULL)
         {          {
             return(NULL);              return(NULL);
Line 2349  nom_segment(unsigned char *chemin, pid_t Line 2618  nom_segment(unsigned char *chemin, pid_t
 }  }
   
   
   /*
   ================================================================================
     Fonctions d'envoi d'un signal à un thread ou à un processus.
   ================================================================================
     Entrée : processus et signal
   --------------------------------------------------------------------------------
     Sortie : erreur
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
 int  int
 envoi_signal_processus(pid_t pid, enum signaux_rpl signal)  envoi_signal_processus(pid_t pid, enum signaux_rpl signal,
           logical1 test_ouverture)
 {  {
     int                             segment;  #   ifndef OS2
           int                         segment;
   #   endif
   
   #   ifndef IPCS_SYSV
           sem_t                       *semaphore;
           sem_t                       *signalisation;
   #   else
           sem_t                       *semaphore;
           sem_t                       *signalisation;
   #       ifndef OS2
               int                     desc;
               key_t                   clef;
   #       endif
   #   endif
   
     struct_queue_signaux            *queue;      struct_queue_signaux            *queue;
   
       struct timespec                 attente;
   
     unsigned char                   *nom;      unsigned char                   *nom;
   
     // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en      // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
Line 2370  envoi_signal_processus(pid_t pid, enum s Line 2668  envoi_signal_processus(pid_t pid, enum s
             return(1);              return(1);
         }          }
   
         if (pthread_mutex_lock(&((*s_queue_signaux).mutex)) != 0)          while(sem_wait(semaphore_queue_signaux) != 0)
         {          {
             return(1);              if (errno != EINTR)
               {
                   return(1);
               }
         }          }
   
         (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]          (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
Line 2384  envoi_signal_processus(pid_t pid, enum s Line 2685  envoi_signal_processus(pid_t pid, enum s
                 ((*s_queue_signaux).pointeur_ecriture + 1)                  ((*s_queue_signaux).pointeur_ecriture + 1)
                 % LONGUEUR_QUEUE_SIGNAUX;                  % LONGUEUR_QUEUE_SIGNAUX;
   
         if (pthread_mutex_unlock(&((*s_queue_signaux).mutex)) != 0)  #       ifndef IPCS_SYSV
           if (msync(s_queue_signaux, sizeof(s_queue_signaux),
                   MS_ASYNC | MS_INVALIDATE) != 0)
         {          {
               sem_post(semaphore_queue_signaux);
             return(1);              return(1);
         }          }
     }  #       endif
     else  
     {  
         // Le signal est envoyé depuis un processus distinct.  
   
         if ((nom = nom_segment(racine_segment, pid)) == NULL)          if (sem_post(semaphore_queue_signaux) != 0)
         {          {
             return(1);              return(1);
         }          }
   
         if ((segment = shm_open(nom, O_RDWR, 0)) == -1)          if (sem_post(semaphore_signalisation) != 0)
         {          {
             free(nom);  
             return(1);              return(1);
         }          }
       }
       else
       {
           // 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 (test_ouverture == d_vrai)
                   {
                       attente.tv_sec = 0;
                       attente.tv_nsec = GRANULARITE_us * 1000;
   
                       while((desc = open(nom, O_RDWR)) == -1)
                       {
                           nanosleep(&attente, NULL);
                           INCR_GRANULARITE(attente.tv_nsec);
                       }
                   }
                   else
                   {
                       if ((desc = open(nom, O_RDWR)) == -1)
                       {
                           sys_free(nom);
                           return(1);
                       }
                   }
   
                   close(desc);
   
                   if ((clef = ftok(nom, 1)) == -1)
                   {
                       sys_free(nom);
                       return(1);
                   }
   
                   sys_free(nom);
   
                   if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
                           == -1)
                   {
                       return(1);
                   }
   
                   queue = shmat(segment, NULL, 0);
   #           else // OS/2
                   if (test_ouverture == d_vrai)
                   {
                       attente.tv_sec = 0;
                       attente.tv_nsec = GRANULARITE_us * 1000;
   
                       while(DosGetNamedSharedMem((PVOID) &queue, nom,
                               PAG_WRITE | PAG_READ) != 0)
                       {
                           nanosleep(&attente, NULL);
                           INCR_GRANULARITE(attente.tv_nsec);
                       }
                   }
                   else
                   {
                       if (DosGetNamedSharedMem((PVOID) &queue, nom,
                               PAG_WRITE | PAG_READ) != 0)
                       {
                           sys_free(nom);
                           return(1);
                       }
                   }
   
                   sys_free(nom);
   #           endif
   #       else // POSIX
               if ((nom = nom_segment(racine_segment, pid)) == NULL)
               {
                   return(1);
               }
   
               if (test_ouverture == d_vrai)
               {
                   attente.tv_sec = 0;
                   attente.tv_nsec = GRANULARITE_us * 1000;
   
                   while((segment = shm_open(nom, O_RDWR, 0)) == -1)
                   {
                       nanosleep(&attente, NULL);
                       INCR_GRANULARITE(attente.tv_nsec);
                   }
               }
               else
               {
                   if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
                   {
                       sys_free(nom);
                       return(1);
                   }
               }
   
               sys_free(nom);
   
               if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
                       PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
                       MAP_FAILED)
               {
                   close(segment);
                   return(1);
               }
   #       endif
   
         free(nom);          // À ce moment, le segment de mémoire partagée est projeté
           // dans l'espace du processus.
   
         if ((queue = mmap(NULL, sizeof(struct_queue_signaux),          if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
                 PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==  
                 MAP_FAILED)  
         {          {
             close(segment);  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
             return(1);              return(1);
         }          }
   
 uprintf("Lock\n");          if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
         if (pthread_mutex_lock(&((*queue).mutex)) != 0)                  == SEM_FAILED)
         {          {
 uprintf("Unlock (error)\n");  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(semaphore);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(semaphore);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(semaphore);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(semaphore);
             return(1);              return(1);
         }          }
   
           while(sem_wait(semaphore) != 0)
           {
               if (errno != EINTR)
               {
   #               ifndef IPCS_SYSV // POSIX
                       if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE)
                               != 0)
                       {
                           munmap(queue, sizeof(struct_queue_signaux));
                           sem_close(semaphore);
                           sem_close(signalisation);
                           close(segment);
                           return(1);
                       }
   
                       if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           close(segment);
                           return(1);
                       }
   
                       close(segment);
   #               else // IPCS_SYSV
   #                   ifndef OS2 // SysV
                           if (shmdt(queue) != 0)
                           {
                               sem_close(semaphore);
                               sem_close(signalisation);
                               return(1);
                           }
   #                   else // OS/2
                           // Pendant de DosGetNamedSHaredMem()
   #                   endif
   #               endif
   
                   sem_close(semaphore);
                   sem_close(signalisation);
                   return(1);
               }
           }
   
         (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();          (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
         (*queue).queue[(*queue).pointeur_ecriture].signal = signal;          (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
   
         (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)          (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
                 % LONGUEUR_QUEUE_SIGNAUX;                  % LONGUEUR_QUEUE_SIGNAUX;
   
 uprintf("Unlock\n");          if (sem_post(semaphore) != 0)
         if (pthread_mutex_unlock(&((*queue).mutex)) != 0)  
         {          {
 uprintf("Unlock failed\n");  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(semaphore);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(semaphore);
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(semaphore);
               sem_close(signalisation);
             return(1);              return(1);
         }          }
   
         if (munmap(queue, sizeof(struct_queue_signaux)) != 0)          if (sem_close(semaphore) != 0)
         {          {
             close(segment);  #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(signalisation);
               return(1);
           }
   
           if (sem_post(signalisation) != 0)
           {
   #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       sem_close(signalisation);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           sem_close(signalisation);
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               sem_close(signalisation);
             return(1);              return(1);
         }          }
   
         close(segment);          if (sem_close(signalisation) != 0)
           {
   #           ifndef IPCS_SYSV // POSIX
                   if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
                   {
                       munmap(queue, sizeof(struct_queue_signaux));
                       close(segment);
                       return(1);
                   }
   
                   if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
                   {
                       close(segment);
                       return(1);
                   }
   
                   close(segment);
   #           else // IPCS_SYSV
   #               ifndef OS2 // SysV
                       if (shmdt(queue) != 0)
                       {
                           return(1);
                       }
   #               else // OS/2
                       // Pendant de DosGetNamedSHaredMem()
   #               endif
   #           endif
   
               return(1);
           }
   
   #       ifndef IPCS_SYSV // POSIX
               if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
               {
                   munmap(queue, sizeof(struct_queue_signaux));
                   close(segment);
                   return(1);
               }
   
               if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
               {
                   close(segment);
                   return(1);
               }
   
               close(segment);
   #       else // IPCS_SYSV
   #           ifndef OS2 // SysV
                   if (shmdt(queue) != 0)
                   {
                       return(1);
                   }
   #           else // OS/2
                   // Pendant de DosGetNamedSHaredMem()
   #           endif
   #       endif
     }      }
   
     return(0);      return(0);
Line 2480  envoi_signal_thread(pthread_t tid, enum Line 3136  envoi_signal_thread(pthread_t tid, enum
         return(1);          return(1);
     }      }
   
     if (pthread_mutex_lock(&mutex_interruptions) != 0)      s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
               .s_etat_processus;
   
       if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
     {      {
         pthread_mutex_unlock(&mutex_liste_threads);          pthread_mutex_unlock(&mutex_liste_threads);
         return(1);          return(1);
     }      }
   
     s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))  
             .s_etat_processus;  
   
     (*s_etat_processus).signaux_en_queue      (*s_etat_processus).signaux_en_queue
             [(*s_etat_processus).pointeur_signal_ecriture] = signal;              [(*s_etat_processus).pointeur_signal_ecriture] = signal;
     (*s_etat_processus).pointeur_signal_ecriture =      (*s_etat_processus).pointeur_signal_ecriture =
             ((*s_etat_processus).pointeur_signal_ecriture + 1)              ((*s_etat_processus).pointeur_signal_ecriture + 1)
             % LONGUEUR_QUEUE_SIGNAUX;              % LONGUEUR_QUEUE_SIGNAUX;
   
     if (pthread_mutex_unlock(&mutex_interruptions) != 0)      if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
     {      {
         pthread_mutex_unlock(&mutex_liste_threads);          pthread_mutex_unlock(&mutex_liste_threads);
         return(1);          return(1);
Line 2506  envoi_signal_thread(pthread_t tid, enum Line 3162  envoi_signal_thread(pthread_t tid, enum
         return(1);          return(1);
     }      }
   
       if (sem_post(semaphore_signalisation) != 0)
       {
           return(1);
       }
   
     return(0);      return(0);
 }  }
   
Line 2513  int Line 3174  int
 envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,  envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
         enum signaux_rpl signal)          enum signaux_rpl signal)
 {  {
     pthread_mutex_lock(&mutex_interruptions);      pthread_mutex_lock(&((*s_etat_processus_a_signaler).mutex_signaux));
     (*s_etat_processus_a_signaler).signaux_en_queue      (*s_etat_processus_a_signaler).signaux_en_queue
             [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =              [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =
             signal;              signal;
     (*s_etat_processus_a_signaler).pointeur_signal_ecriture =      (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
             ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)              ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
             % LONGUEUR_QUEUE_SIGNAUX;              % LONGUEUR_QUEUE_SIGNAUX;
     pthread_mutex_unlock(&mutex_interruptions);      pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
   
       if (sem_post(semaphore_signalisation) != 0)
       {
           return(1);
       }
   
     return(0);      return(0);
 }  }
Line 2542  envoi_signal_contexte(struct_processus * Line 3208  envoi_signal_contexte(struct_processus *
 void  void
 creation_queue_signaux(struct_processus *s_etat_processus)  creation_queue_signaux(struct_processus *s_etat_processus)
 {  {
     pthread_mutexattr_t             attributs_mutex;      pthread_attr_t                  attributs;
   
     unsigned char                   *nom;      unsigned char                   *nom;
   
     racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;      racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
   
 #   ifndef IPCS_SYSV // POSIX  #   ifndef IPCS_SYSV // POSIX
           if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
                   getpid())) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,          if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
             getpid())) == NULL)                  S_IRUSR | S_IWUSR)) == -1)
     {          {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              if (errno != EEXIST)
         return;              {
     }                  sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,              if ((*s_etat_processus).langue == 'F')
             S_IRUSR | S_IWUSR)) == -1)              {
     {                  printf("+++Attention : Le segment de mémoire %s préexiste !\n",
         free(nom);                          nom);
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              }
         return;              else
     }              {
                   printf("+++Warning: %s memory segment preexists!\n", nom);
               }
   
     if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)              if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_TRUNC,
     {                      S_IRUSR | S_IWUSR)) == -1)
         free(nom);              {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  sys_free(nom);
         return;                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
     }                  return;
               }
           }
   
     s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),          if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
             PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);          {
               sys_free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
     if (((void *) s_queue_signaux) == ((void *) -1))          s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
     {                  PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
         if (shm_unlink(nom) == -1)  
           if (((void *) s_queue_signaux) == ((void *) -1))
         {          {
             free(nom);              if (shm_unlink(nom) == -1)
               {
                   sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               sys_free(nom);
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return;              return;
         }          }
   
         free(nom);          sys_free(nom);
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     free(nom);          if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
                   == SEM_FAILED)
           {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
     pthread_mutexattr_init(&attributs_mutex);          if ((semaphore_signalisation = sem_init2(0, getpid(),
     pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_NORMAL);                  SEM_SIGNALISATION)) == SEM_FAILED)
     pthread_mutex_init(&((*s_queue_signaux).mutex), &attributs_mutex);          {
     pthread_mutexattr_destroy(&attributs_mutex);              (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
     (*s_queue_signaux).pointeur_lecture = 0;          if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
     (*s_queue_signaux).pointeur_ecriture = 0;                  SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
           {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   
     if (msync(s_queue_signaux, sizeof(struct_queue_signaux), 0))          (*s_queue_signaux).pointeur_lecture = 0;
     {          (*s_queue_signaux).pointeur_ecriture = 0;
         (*s_etat_processus).erreur_systeme = d_es_processus;  
         return;  
     }  
   
 #   else // SystemV          (*s_queue_signaux).requete_arret = d_faux;
 #   ifndef OS2  
   
     file                            *desc;          if (msync(s_queue_signaux, sizeof(struct_queue_signaux),
                   MS_ASYNC | MS_INVALIDATE) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
   #   else // IPCS_SYSV
   #       ifndef OS2
               int                             segment;
               int                             support;
   
     key_t                           clef;              key_t                           clef;
   
     // Création d'un segment de données associé au PID du processus courant              // Création d'un segment de données associé au PID du processus
               // courant
   
     chemin = (*s_etat_processus).chemin_fichiers_temporaires;              if ((nom = nom_segment((*s_etat_processus)
                       .chemin_fichiers_temporaires, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,              if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
             getpid())) == NULL)                      S_IRUSR | S_IWUSR)) == -1)
     {              {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
         return;                  return;
     }              }
   
               if ((clef = ftok(nom, 1)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               close(support);
               sys_free(nom);
   
     if ((desc = fopen(nom, "w")) == NULL)              if ((segment = shmget(clef, sizeof(struct_queue_signaux),
                       IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               s_queue_signaux = shmat(segment, NULL, 0);
               f_queue_signaux = segment;
   
               if (((void *) s_queue_signaux) == ((void *) -1))
               {
                   if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return;
                   }
   
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               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(0, getpid(),
                       SEM_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
                       SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       else // OS/2
               if ((nom = nom_segment(NULL, getpid())) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
                       sizeof(struct_queue_signaux),
                       PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
               {
                   sys_free(nom);
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               sys_free(nom);
   
               sem_init(&((*s_queue_signaux).semaphore), 1, 1);
               sem_init(&((*s_queue_signaux).signalisation), 1, 0);
               sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
   
               (*s_queue_signaux).pointeur_lecture = 0;
               (*s_queue_signaux).pointeur_ecriture = 0;
               (*s_queue_signaux).requete_arret = d_faux;
   #       endif
   #   endif
   
       (*s_queue_signaux).controle = getpid();
   
       if (lancement_thread_signaux(s_etat_processus) == d_erreur)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     fclose(desc);      // Lancement du thread de récupération des signaux.
   
     if ((clef = ftok(nom, 1)) == -1)      if (pthread_attr_init(&attributs) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     free(nom);      if (pthread_attr_setdetachstate(&attributs,
               PTHREAD_CREATE_JOINABLE) != 0)
     if ((segment = shmget(clef,  
             nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),  
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     fifos = shmat(segment, NULL, 0);      if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
               thread_surveillance_signaux, s_etat_processus) != 0)
     if (((void *) fifos) == ((void *) -1))  
     {      {
         if (shmctl(segment, IPC_RMID, 0) == -1)          (*s_etat_processus).erreur_systeme = d_es_processus;
         {  
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
             return;  
         }  
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;          return;
     }      }
   
 #   else      if (pthread_attr_destroy(&attributs) != 0)
   
     if ((nom = nom_segment(NULL, getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     if (DosAllocSharedMem(&ptr_os2, nom, nombre_queues *  #   ifndef IPCS_SYSV
             ((2 * longueur_queue) + 4) * sizeof(int),      if (msync(s_queue_signaux, sizeof(s_queue_signaux),
             PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)              MS_ASYNC | MS_INVALIDATE) != 0)
     {      {
         free(nom);          (*s_etat_processus).erreur_systeme = d_es_processus;
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;          return;
     }      }
   
     free(nom);  
     fifos = ptr_os2;  
   
 #   endif  
 #   endif  #   endif
   
     return;      return;
Line 2706  liberation_queue_signaux(struct_processu Line 3484  liberation_queue_signaux(struct_processu
 {  {
 #   ifdef IPCS_SYSV // SystemV  #   ifdef IPCS_SYSV // SystemV
 #       ifndef OS2  #       ifndef OS2
               if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
 #       else // OS/2  #       else // OS/2
 #       endif  #       endif
 #   else // POSIX  #   else // POSIX
           sem_close(semaphore_queue_signaux);
           sem_close(semaphore_signalisation);
           sem_close(semaphore_arret_signalisation);
   
         if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)          if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
Line 2738  liberation_queue_signaux(struct_processu Line 3525  liberation_queue_signaux(struct_processu
 void  void
 destruction_queue_signaux(struct_processus *s_etat_processus)  destruction_queue_signaux(struct_processus *s_etat_processus)
 {  {
     unsigned char       *nom;  
   
 #   ifdef IPCS_SYSV // SystemV  
 #   ifndef OS2  #   ifndef OS2
           unsigned char       *nom;
   #   endif
   
       // On dépile les interruptions pour arrêter les SIGUSR2 sur
       // le processus courant.
   
     if (shmdt(fifos) == -1)      scrutation_interruptions(s_etat_processus);
   
       while(sem_wait(semaphore_arret_signalisation) != 0)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if (errno != EINTR)
         return;          {
               (*s_etat_processus).erreur_systeme = d_es_processus;
               return;
           }
     }      }
   
     if (shmctl(segment, IPC_RMID, 0) == -1)      (*s_queue_signaux).requete_arret = d_vrai;
   
   #   ifndef IPCS_SYSV
       msync(s_queue_signaux, sizeof(s_queue_signaux), MS_ASYNC | MS_INVALIDATE);
   #   endif
   
       sem_post(semaphore_arret_signalisation);
   
       // Incrémenter le sémaphore pour être sûr de le débloquer.
   
       sem_post(semaphore_signalisation);
   
       if ((*s_queue_signaux).controle == getpid())
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          pthread_join((*s_queue_signaux).thread_signaux, NULL);
         return;  
     }      }
       else
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,  
             getpid())) == NULL)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_processus;
         return;          return;
     }      }
   
     // FERMER LE FICHIER      arret_thread_signaux(s_etat_processus);
   
     unlink(nom);  #   ifdef IPCS_SYSV // SystemV
     free(nom);  #       ifndef OS2
               // Il faut commencer par éliminer le sémaphore.
   
 #   else              if (semctl((*semaphore_queue_signaux).sem, 0, IPC_RMID) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
     if (DosFreeMem(fifos) != 0)              unlink((*semaphore_queue_signaux).path);
     {              sys_free((*semaphore_queue_signaux).path);
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     // FERMER LE FICHIER              if (semctl((*semaphore_signalisation).sem, 0, IPC_RMID) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_processus;
                   return;
               }
   
 #   endif              unlink((*semaphore_signalisation).path);
 #   else // POSIX              sys_free((*semaphore_signalisation).path);
   
     if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)              if (semctl((*semaphore_arret_signalisation).sem, 0, IPC_RMID) == -1)
     {              {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  (*s_etat_processus).erreur_systeme = d_es_processus;
         return;                  return;
     }              }
   
     if ((nom = nom_segment(NULL, getpid())) == NULL)              unlink((*semaphore_arret_signalisation).path);
     {              sys_free((*semaphore_arret_signalisation).path);
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     close(f_queue_signaux);              if (shmdt(s_queue_signaux) == -1)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
     if (shm_unlink(nom) != 0)              if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
     {              {
         free(nom);                  (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  return;
         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);
               sys_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));
   
               sem_close(&((*s_queue_signaux).arret_signalisation));
               sem_destroy(&((*s_queue_signaux).arret_signalisation));
   
               if (DosFreeMem(s_queue_signaux) != 0)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   #       endif
   #   else // POSIX
           sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
           sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
           sem_destroy2(semaphore_arret_signalisation, getpid(),
                   SEM_ARRET_SIGNALISATION);
   
           if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           if ((nom = nom_segment(NULL, getpid())) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           close(f_queue_signaux);
   
     free(nom);          if (shm_unlink(nom) != 0)
           {
               sys_free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           sys_free(nom);
 #   endif  #   endif
   
     return;      return;

Removed from v.1.69  
changed lines
  Added in v.1.198


CVSweb interface <joel.bertrand@systella.fr>