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

version 1.33, 2010/08/22 16:38:36 version 1.67, 2011/09/14 14:34:28
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.18    RPL/2 (R) version 4.1.3
   Copyright (C) 1989-2010 Dr. BERTRAND Joël    Copyright (C) 1989-2011 Dr. BERTRAND Joël
   
   This file is part of RPL/2.    This file is part of RPL/2.
   
Line 183  insertion_thread_surveillance(struct_pro Line 183  insertion_thread_surveillance(struct_pro
         }          }
     }      }
   
     pthread_mutex_lock(&((*s_argument_thread).mutex));      pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references));
     (*s_argument_thread).nombre_references++;      (*s_argument_thread).nombre_references++;
     pthread_mutex_unlock(&((*s_argument_thread).mutex));      pthread_mutex_unlock(&((*s_argument_thread).mutex_nombre_references));
   
     (*l_nouvel_objet).suivant = liste_threads_surveillance;      (*l_nouvel_objet).suivant = liste_threads_surveillance;
     (*l_nouvel_objet).donnee = (void *) s_argument_thread;      (*l_nouvel_objet).donnee = (void *) s_argument_thread;
Line 378  retrait_thread_surveillance(struct_proce Line 378  retrait_thread_surveillance(struct_proce
         (*l_element_precedent).suivant = (*l_element_courant).suivant;          (*l_element_precedent).suivant = (*l_element_courant).suivant;
     }      }
   
     if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)      if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
               != 0)
     {      {
 #       ifndef SEMAPHORES_NOMMES  #       ifndef SEMAPHORES_NOMMES
         sem_post(&semaphore_liste_threads);          sem_post(&semaphore_liste_threads);
Line 400  retrait_thread_surveillance(struct_proce Line 401  retrait_thread_surveillance(struct_proce
   
     if ((*s_argument_thread).nombre_references == 0)      if ((*s_argument_thread).nombre_references == 0)
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             sem_post(&semaphore_liste_threads);              sem_post(&semaphore_liste_threads);
Line 415  retrait_thread_surveillance(struct_proce Line 417  retrait_thread_surveillance(struct_proce
         }          }
   
         pthread_mutex_destroy(&((*s_argument_thread).mutex));          pthread_mutex_destroy(&((*s_argument_thread).mutex));
           pthread_mutex_destroy(&((*s_argument_thread).mutex_nombre_references));
         free(s_argument_thread);          free(s_argument_thread);
     }      }
     else      else
     {      {
         if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_unlock(&((*s_argument_thread)
                   .mutex_nombre_references)) != 0)
         {          {
 #           ifndef SEMAPHORES_NOMMES  #           ifndef SEMAPHORES_NOMMES
             sem_post(&semaphore_liste_threads);              sem_post(&semaphore_liste_threads);
Line 676  liberation_threads(struct_processus *s_e Line 680  liberation_threads(struct_processus *s_e
                 s_argument_thread = (struct_descripteur_thread *)                  s_argument_thread = (struct_descripteur_thread *)
                         (*((struct_liste_chainee *) element_courant)).donnee;                          (*((struct_liste_chainee *) element_courant)).donnee;
   
                 if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)                  if (pthread_mutex_lock(&((*s_argument_thread)
                           .mutex_nombre_references)) != 0)
                 {                  {
                     (*s_etat_processus).erreur_systeme = d_es_processus;                      (*s_etat_processus).erreur_systeme = d_es_processus;
                     sem_post(&semaphore_liste_threads);                      sem_post(&semaphore_liste_threads);
Line 700  liberation_threads(struct_processus *s_e Line 705  liberation_threads(struct_processus *s_e
                     close((*s_argument_thread)                      close((*s_argument_thread)
                             .pipe_nombre_interruptions_attente[0]);                              .pipe_nombre_interruptions_attente[0]);
   
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          sem_post(&semaphore_liste_threads);
Line 709  liberation_threads(struct_processus *s_e Line 714  liberation_threads(struct_processus *s_e
                     }                      }
   
                     pthread_mutex_destroy(&((*s_argument_thread).mutex));                      pthread_mutex_destroy(&((*s_argument_thread).mutex));
                       pthread_mutex_destroy(&((*s_argument_thread)
                               .mutex_nombre_references));
   
                     if ((*s_argument_thread).processus_detache == d_faux)                      if ((*s_argument_thread).processus_detache == d_faux)
                     {                      {
Line 723  liberation_threads(struct_processus *s_e Line 730  liberation_threads(struct_processus *s_e
                 }                  }
                 else                  else
                 {                  {
                     if (pthread_mutex_unlock(&((*s_argument_thread).mutex))                      if (pthread_mutex_unlock(&((*s_argument_thread)
                             != 0)                              .mutex_nombre_references)) != 0)
                     {                      {
                         (*s_etat_processus).erreur_systeme = d_es_processus;                          (*s_etat_processus).erreur_systeme = d_es_processus;
                         sem_post(&semaphore_liste_threads);                          sem_post(&semaphore_liste_threads);
Line 796  liberation_threads(struct_processus *s_e Line 803  liberation_threads(struct_processus *s_e
                 }                  }
             }              }
   
             for(i = 0; i < (*s_etat_processus).nombre_variables; i++)              liberation_arbre_variables(s_etat_processus,
             {                      (*s_etat_processus).s_arbre_variables, d_faux);
                 pthread_mutex_trylock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
                 pthread_mutex_unlock(&((*(*s_etat_processus)  
                         .s_liste_variables[i].objet).mutex));  
   
                 // Les variables de niveau 0 sont des définitions qui  
                 // ne sont pas copiées entre threads.  
                 if ((*s_etat_processus).s_liste_variables[i].niveau > 0)  
                 {  
                     liberation(s_etat_processus,  
                             (*s_etat_processus).s_liste_variables[i].objet);  
                 }  
   
                 free((*s_etat_processus).s_liste_variables[i].nom);  
             }  
   
             free((*s_etat_processus).s_liste_variables);  
   
             for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)              for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)
             {              {
Line 1328  liberation_threads(struct_processus *s_e Line 1318  liberation_threads(struct_processus *s_e
             sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork);              sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork);
 #           endif  #           endif
   
               liberation_contexte_cas(s_etat_processus);
             free(s_etat_processus);              free(s_etat_processus);
   
             s_etat_processus = candidat;              s_etat_processus = candidat;
Line 1350  liberation_threads(struct_processus *s_e Line 1341  liberation_threads(struct_processus *s_e
         s_argument_thread = (struct_descripteur_thread *)          s_argument_thread = (struct_descripteur_thread *)
                 (*l_element_courant).donnee;                  (*l_element_courant).donnee;
   
         if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)          if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
                   != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_processus;              (*s_etat_processus).erreur_systeme = d_es_processus;
             sem_post(&semaphore_liste_threads);              sem_post(&semaphore_liste_threads);
Line 1373  liberation_threads(struct_processus *s_e Line 1365  liberation_threads(struct_processus *s_e
             close((*s_argument_thread).pipe_interruptions[0]);              close((*s_argument_thread).pipe_interruptions[0]);
             close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);              close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);
   
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  sem_post(&semaphore_liste_threads);
Line 1381  liberation_threads(struct_processus *s_e Line 1374  liberation_threads(struct_processus *s_e
             }              }
   
             pthread_mutex_destroy(&((*s_argument_thread).mutex));              pthread_mutex_destroy(&((*s_argument_thread).mutex));
               pthread_mutex_destroy(&((*s_argument_thread)
                       .mutex_nombre_references));
   
             if ((*s_argument_thread).processus_detache == d_faux)              if ((*s_argument_thread).processus_detache == d_faux)
             {              {
Line 1394  liberation_threads(struct_processus *s_e Line 1389  liberation_threads(struct_processus *s_e
         }          }
         else          else
         {          {
             if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)              if (pthread_mutex_unlock(&((*s_argument_thread)
                       .mutex_nombre_references)) != 0)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_processus;                  (*s_etat_processus).erreur_systeme = d_es_processus;
                 sem_post(&semaphore_liste_threads);                  sem_post(&semaphore_liste_threads);
Line 1461  recherche_thread(pid_t pid, pthread_t ti Line 1457  recherche_thread(pid_t pid, pthread_t ti
     return(s_etat_processus);      return(s_etat_processus);
 }  }
   
 static logical1  static struct_processus *
 recherche_thread_principal(pid_t pid, pthread_t *thread)  recherche_thread_principal(pid_t pid)
 {  {
     volatile struct_liste_chainee_volatile      *l_element_courant;      volatile struct_liste_chainee_volatile      *l_element_courant;
   
Line 1486  recherche_thread_principal(pid_t pid, pt Line 1482  recherche_thread_principal(pid_t pid, pt
          * Le processus n'existe plus. On ne distribue aucun signal.           * Le processus n'existe plus. On ne distribue aucun signal.
          */           */
   
         return(d_faux);          return(NULL);
     }      }
   
     (*thread) = (*((struct_thread *) (*l_element_courant).donnee)).tid;      return((*((struct_thread *) (*l_element_courant).donnee))
               .s_etat_processus);
     return(d_vrai);  
 }  }
   
   
Line 1592  verrouillage_gestionnaire_signaux() Line 1587  verrouillage_gestionnaire_signaux()
         // ce que ce soit possible.          // ce que ce soit possible.
   
 #       ifndef SEMAPHORES_NOMMES  #       ifndef SEMAPHORES_NOMMES
         while(sem_trywait(&semaphore_liste_threads) == -1)          while(sem_wait(&semaphore_liste_threads) == -1)
 #       else  #       else
         while(sem_trywait(semaphore_liste_threads) == -1)          while(sem_wait(semaphore_liste_threads) == -1)
 #       endif  #       endif
         {          {
             if ((errno != EINTR) && (errno != EAGAIN))              if (errno != EINTR)
             {              {
                 pthread_sigmask(SIG_SETMASK, &oldset, NULL);                  pthread_sigmask(SIG_SETMASK, &oldset, NULL);
   
Line 1613  verrouillage_gestionnaire_signaux() Line 1608  verrouillage_gestionnaire_signaux()
                 BUG(1, uprintf("Lock error !\n"));                  BUG(1, uprintf("Lock error !\n"));
                 return;                  return;
             }              }
   
             sched_yield();  
         }          }
     }      }
   
Line 1724  deverrouillage_gestionnaire_signaux() Line 1717  deverrouillage_gestionnaire_signaux()
     return;      return;
 }  }
   
 #ifdef _BROKEN_SIGINFO  #define test_signal(signal) \
       if (signal_test == SIGTEST) { signal_test = signal; return; }
 // Remplacer les mutexes par des sémaphores SysV  
   
 #define longueur_queue  256  
 #define nombre_queues   13  
   
 static int              *fifos;  
 static int              segment;  
 static sem_t            *semaphores[nombre_queues];  
 static sem_t            *semaphore_global;  
   
 #ifdef IPCS_SYSV  
 static unsigned char    *chemin = NULL;  
 #endif  
   
 unsigned char *  
 nom_segment(unsigned char *chemin, pid_t pid)  
 {  
     unsigned char               *fichier;  
   
 #   ifdef IPCS_SYSV  
     if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);  
 #   else  
     if ((fichier = malloc((1 + 256 + 1) *  
             sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);  // Récupération des signaux
 #   endif  // - SIGINT (arrêt au clavier)
   // - SIGTERM (signal d'arrêt en provenance du système)
     return(fichier);  
 }  
   
 unsigned char *  void
 nom_semaphore(pid_t pid, int queue)  interruption1(int signal)
 {  {
     unsigned char               *fichier;      test_signal(signal);
   
     if ((fichier = malloc((256 + 1) * sizeof(unsigned char))) == NULL)  
     {  
         return(NULL);  
     }  
   
     sprintf(fichier, "/RPL-SIGESMAPHORES-%d-%d", (int) pid, queue);  
   
     return(fichier);  
 }  
   
 inline int  
 queue_de_signal(int signal)  
 {  
     switch(signal)      switch(signal)
     {      {
         case SIGINT:          case SIGINT:
             return(0);              envoi_signal_processus(getpid(), rpl_sigint);
         case SIGTSTP:              break;
             return(1);  
         case SIGCONT:          case SIGTERM:
             return(2);              envoi_signal_processus(getpid(), rpl_sigterm);
         case SIGURG:              break;
             return(3);  
         case SIGPIPE:  
             return(4);  
         case SIGALRM:          case SIGALRM:
             return(5);              envoi_signal_processus(getpid(), rpl_sigalrm);
         case SIGFSTOP:              break;
             return(6);  
         case SIGSTART:  
             return(7);  
         case SIGINJECT:  
             return(8);  
         case SIGABORT:  
             return(9);  
         case SIGFABORT:  
             return(10);  
         case SIGSEGV:  
             return(11);  
         case SIGBUS:  
             return(12);  
     }      }
   
     return(-1);      return;
 }  }
   
 void  inline static void
 creation_fifos_signaux(struct_processus *s_etat_processus)  signal_alrm(struct_processus *s_etat_processus, pid_t pid)
 {  {
     /*      struct_processus        *s_thread_principal;
      * Signaux utilisés  
      * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP,  
      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT  
      */  
   
 #   ifndef IPCS_SYSV // POSIX  
 #   else // SystemV  
   
     file                            *desc;      verrouillage_gestionnaire_signaux();
   
     int                             i;  
   
     key_t                           clef;  
   
     unsigned char                   *nom;  
   
     // 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 ((desc = fopen(nom, "w")) == NULL)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;  
         return;  
     }  
   
     fclose(desc);  
   
     if ((clef = ftok(nom, 1)) == -1)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     free(nom);  
   
     if ((segment = shmget(clef,      if (pid == getpid())
             nombre_queues * (longueur_queue + 4) * sizeof(int),  
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Si pid est égal à getpid(), le signal à traiter est issu
         return;          // du même processus que celui qui va le traiter, mais d'un thread
     }          // différent.
   
     fifos = shmat(segment, NULL, 0);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
   
     if (((void *) fifos) == ((void *) -1))  
     {  
         if (shmctl(segment, IPC_RMID, 0) == -1)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
             return;                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
   
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          if ((*s_etat_processus).pid_processus_pere != getpid())
         return;  
     }  
   
 #   endif  
   
     /*  
      * Structure d'une queue  
      * 0 : pointeur en lecture sur le premier emplacement libre (int)  
      * 1 : pointeur en écriture sur le premier emplacement à lire (int)  
      * 2 : longueur de la queue (int)  
      * 3 : éléments restants (int)  
      * 4 à 4 + (2) : queue (int)  
      */  
   
     for(i = 0; i < nombre_queues; i++)  
     {  
         fifos[(i * (longueur_queue + 4))] = 0;  
         fifos[(i * (longueur_queue + 4)) + 1] = 0;  
         fifos[(i * (longueur_queue + 4)) + 2] = longueur_queue;  
         fifos[(i * (longueur_queue + 4)) + 3] = longueur_queue;  
     }  
   
     // Création des sémaphores : un sémaphore par signal et par queue  
     // plus un sémaphore global pour tous les threads.  
   
     for(i = 0; i < nombre_queues; i++)  
     {  
         if ((nom = nom_semaphore(getpid(), i)) == NULL)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              // On n'est pas dans le processus père, on remonte le signal.
             return;              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigalrm);
         }          }
           else
         // Le sémaphore est créé en écrasant si nécessaire un sémaphore  
         // préexistant. Comme le nom du sémaphore contient l'identifiant du  
         // processus, il est anormal d'avoir un sémaphore de même nom  
         // préexistant.  
   
         if ((semaphores[i] = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,  
                 1)) == SEM_FAILED)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              // On est dans le processus père, on effectue un arrêt d'urgence.
             return;              (*s_etat_processus).var_volatile_alarme = -1;
               (*s_etat_processus).var_volatile_requete_arret = -1;
         }          }
   
         free(nom);  
     }      }
       else
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     if ((semaphore_global = sem_open(nom, O_CREAT, S_IRUSR | S_IWUSR,  
             1)) == SEM_FAILED)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_semaphore;  
         return;  
     }  
   
     free(nom);  
   
     return;  
 }  
   
 void  
 liberation_fifos_signaux(struct_processus *s_etat_processus)  
 {  
     int                 i;  
   
     if (shmdt(fifos) == -1)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          // Le signal est issu d'un processus différent. On recherche le
         return;          // thread principal pour remonter le signal.
     }  
   
     for(i = 0; i < nombre_queues; i++)          if ((s_thread_principal = recherche_thread_principal(getpid()))
     {                  != NULL)
         if (sem_close(semaphores[i]) != 0)  
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
             return;  
         }          }
     }      }
   
     if (sem_close(semaphore_global) != 0)      deverrouillage_gestionnaire_signaux();
     {  
         (*s_etat_processus).erreur_systeme = d_es_semaphore;  
         return;  
     }  
   
     return;      return;
 }  }
   
 void  inline static void
 destruction_fifos_signaux(struct_processus *s_etat_processus)  signal_term(struct_processus *s_etat_processus, pid_t pid)
 {  {
     int                 i;      struct_processus        *s_thread_principal;
       volatile sig_atomic_t   exclusion = 0;
     unsigned char       *nom;  
   
     if (shmdt(fifos) == -1)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     if (shmctl(segment, IPC_RMID, 0) == -1)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,  
             getpid())) == NULL)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     unlink(nom);      verrouillage_gestionnaire_signaux();
     free(nom);  
   
     for(i = 0; i < nombre_queues; i++)      if (pid == getpid())
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
             return;                      (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
   
         if (sem_unlink(nom) != 0)          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             (*s_etat_processus).erreur_systeme = d_es_semaphore;              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
             return;                      rpl_sigterm);
         }          }
           else
           {
               (*s_etat_processus).var_volatile_traitement_sigint = -1;
   
         free(nom);              while(exclusion == 1);
     }              exclusion = 1;
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;  
         return;  
     }  
   
     if (sem_unlink(nom) != 0)  
     {  
         (*s_etat_processus).erreur_systeme = d_es_semaphore;  
         return;  
     }  
   
     free(nom);  
   
     return;  
 }  
   
 int  
 queue_in(pid_t pid, int signal)  
 {  
 #undef printf  
 // Transformer ce truc en POSIX ! On ne fait du SysV que si on n'a pas le choix  
   
 #   ifndef IPCS_SYSV  
 #   else // Traitement à l'aide d'IPCS SystemV  
   
     int             *base;  
     int             *buffer;  
     int             *projection_fifos;  
     int             queue;  
     int             identifiant;  
   
     key_t           clef;  
   
     sem_t           *semaphore;  
   
     struct stat     s_stat;  
   
     unsigned char   *nom;  
   
     queue = queue_de_signal(signal);  
   
     // Ouverture des projections  
   
     if ((nom = nom_segment(chemin, pid)) == NULL)  
     {  
         return(-1);  
     }  
   
     // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,  
     // il convient d'attendre que le fichier support soit effectivement  
     // accessible. Dans tous les autres cas, ce fichier doit exister. S'il  
     // n'existe plus, le processus associé n'existe plus.  
   
     if (signal == SIGSTART)  
     {  
         // On attend que le fichier sois présent  
   
         while(stat(nom, &s_stat) != 0);              if ((*s_etat_processus).var_volatile_requete_arret == -1)
     }              {
                   deverrouillage_gestionnaire_signaux();
     if ((clef = ftok(nom, 1)) == -1)                  exclusion = 0;
     {                  return;
         return(-1);              }
     }  
   
     free(nom);              (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
     if (signal == SIGSTART)              exclusion = 0;
     {          }
         while((identifiant = shmget(clef,  
                 nombre_queues * (longueur_queue + 4) * sizeof(int),  
                 S_IRUSR | S_IWUSR)) == -1);  
     }      }
     else      else
     {      {
         if ((identifiant = shmget(clef,          if ((s_thread_principal = recherche_thread_principal(getpid()))
                 nombre_queues * (longueur_queue + 4) * sizeof(int),                  != NULL)
                 S_IRUSR | S_IWUSR)) == -1)  
         {          {
             return(-1);              envoi_signal_contexte(s_thread_principal, rpl_sigterm);
         }          }
     }      }
   
     projection_fifos = shmat(identifiant, NULL, 0);      deverrouillage_gestionnaire_signaux();
       return;
     if (((void *) projection_fifos) == ((void *) -1))  
     {  
         return(-1);  
     }  
   
     if ((nom = nom_semaphore(pid, queue)) == NULL)  
     {  
         shmdt(projection_fifos);  
         return(-1);  
     }  
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);  
   
     if (sem_wait(semaphore) != 0)  
     {  
         shmdt(projection_fifos);  
         return(-1);  
     }  
   
     // Il ne faut pas empiler plusieurs SIGSTART car SIGSTART peut provenir  
     // de l'instruction SWI. Plusieurs threads peuvent interrompre de façon  
     // asynchrone le processus père durant une phase de signaux masqués.  
   
     base = &(projection_fifos[(longueur_queue + 4) * queue]);  
     buffer = &(base[4]);  
   
     // base[3] contient le nombre d'éléments restants  
   
     if (base[3] <= 0)  
     {  
         sem_post(semaphore);  
         sem_close(semaphore);  
         shmdt(projection_fifos);  
         return(-1);  
     }  
   
     base[3]--;  
   
     // base[1] contient le prochain élément à écrire  
     buffer[base[1]++] = (int) pid;  
     base[1] %= base[2];  
   
     if (sem_post(semaphore) != 0)  
     {  
         shmdt(projection_fifos);  
         sem_close(semaphore);  
         return(-1);  
     }  
   
     sem_close(semaphore);  
   
     // Fermeture des projections  
     shmdt(projection_fifos);  
   
 #   endif  
   
     return(0);  
 }  
   
 pid_t  
 origine_signal(int signal)  
 {  
     int             *base;  
     int             *buffer;  
     int             pid;  
     int             queue;  
   
     queue = queue_de_signal(signal);  
   
     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",  
             (int) getpid(), signal));  
   
     if (sem_wait(semaphores[queue]) != 0)  
     {  
         return(-1);  
     }  
   
     // Le signal SIGCONT peut être envoyé de façon totalement asynchrone.  
     // Il peut y avoir plus de signaux envoyés que d'interruptions traitées.  
     // Il convient donc de rectifier la queue lors du traitement de  
     // l'interruption correspondante. Le gestionnaire étant installé sans  
     // l'option NODEFER, la queue reste cohérente.  
   
     if (signal == SIGCONT)  
     {  
         base = &(fifos[(longueur_queue + 4) * queue]);  
         buffer = &(base[4]);  
         base[0] = (base[1] - 1) % base[2];  
         pid = buffer[base[0]++];  
         base[3] = base[2];  
     }  
     else  
     {  
         base = &(fifos[(longueur_queue + 4) * queue]);  
         buffer = &(base[4]);  
         pid = buffer[base[0]++];  
         base[0] %= base[2];  
         base[3]++;  
     }  
   
     if (base[3] > base[2])  
     {  
         sem_post(semaphores[queue]);  
         return(-1);  
     }  
   
     if (sem_post(semaphores[queue]) != 0)  
     {  
         return(-1);  
     }  
   
     return((pid_t) pid);  
 }  }
   
 #endif  inline static void
   signal_int(struct_processus *s_etat_processus, pid_t pid)
 #ifdef printf  
 #   undef printf  
 #endif  
   
 void  
 interruption1(SIGHANDLER_ARGS)  
 {  {
     pid_t                   pid;      struct_processus        *s_thread_principal;
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     volatile sig_atomic_t   exclusion = 0;      volatile sig_atomic_t   exclusion = 0;
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO      if (pid == getpid())
     if (signal == SIGINT)  
     {  
         // Si l'interruption provient du clavier, il n'y a pas eu d'appel  
         // à queue_in().  
   
         pid = getpid();  
     }  
     else  
     {      {
         pid = origine_signal(signal);          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     }          {
 #   else              printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
     pid = (*siginfo).si_pid;                      (unsigned long long) pthread_self());
 #   endif              fflush(stdout);
           }
   
     switch(signal)          if ((*s_etat_processus).pid_processus_pere != getpid())
     {  
         case SIGALRM :  
         {          {
             if (pid == getpid())              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
             {                      rpl_sigint);
                 if ((s_etat_processus = recherche_thread(getpid(),          }
                         pthread_self())) == NULL)          else
                 {          {
                     deverrouillage_gestionnaire_signaux();              (*s_etat_processus).var_volatile_traitement_sigint = -1;
                      return;  
                 }  
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              while(exclusion == 1);
                 {              exclusion = 1;
                     printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())              if ((*s_etat_processus).var_volatile_requete_arret == -1)
                 {  
                     kill((*s_etat_processus).pid_processus_pere, signal);  
                 }  
                 else  
                 {  
                     (*s_etat_processus).var_volatile_alarme = -1;  
                     (*s_etat_processus).var_volatile_requete_arret = -1;  
                 }  
             }  
             else  
             {              {
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)                  deverrouillage_gestionnaire_signaux();
                 {                  exclusion = 0;
                     pthread_kill(thread, signal);                  return;
                 }  
             }              }
   
             break;              if ((*s_etat_processus).langue == 'F')
         }  
   
         case SIGINT :  
         {  
             /*  
              * Une vieille spécification POSIX permet au pointeur siginfo  
              * d'être nul dans le cas d'un ^C envoyé depuis le clavier.  
              * Solaris suit en particulier cette spécification.  
              */  
   
 #           ifndef _BROKEN_SIGINFO  
             if (siginfo == NULL)  
             {              {
                 kill(getpid(), signal);                  printf("+++Interruption\n");
             }              }
             else              else
 #           endif  
             if (pid == getpid())  
             {              {
                 if ((s_etat_processus = recherche_thread(getpid(),                  printf("+++Interrupt\n");
                         pthread_self())) == NULL)              }
                 {  
                     deverrouillage_gestionnaire_signaux();  
                     return;  
                 }  
   
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
                 {  
                     printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),  
                             (unsigned long long) pthread_self());  
                     fflush(stdout);  
                 }  
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())  
                 {  
                     kill((*s_etat_processus).pid_processus_pere, signal);  
                 }  
                 else  
                 {  
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;  
   
                     while(exclusion == 1);  
                     exclusion = 1;  
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)  
                     {  
                         deverrouillage_gestionnaire_signaux();  
                         exclusion = 0;  
                         return;  
                     }  
   
                     if (strncmp(getenv("LANG"), "fr", 2) == 0)  
                     {  
                         printf("+++Interruption\n");  
                     }  
                     else  
                     {  
                         printf("+++Interrupt\n");  
                     }  
   
                     fflush(stdout);  
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;              fflush(stdout);
                     (*s_etat_processus).var_volatile_alarme = -1;  
   
                     exclusion = 0;              (*s_etat_processus).var_volatile_requete_arret = -1;
                 }              (*s_etat_processus).var_volatile_alarme = -1;
             }  
             else  
             {  
                 if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
                 {  
                     pthread_kill(thread, signal);  
                 }  
             }  
   
             break;              exclusion = 0;
         }          }
       }
         default :      else
       {
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             BUG(1, uprintf("[%d] Unknown signal %d in this context\n",              envoi_signal_contexte(s_thread_principal, rpl_sigint);
                     (int) getpid(), signal));  
             break;  
         }          }
     }      }
   
Line 2390  interruption1(SIGHANDLER_ARGS) Line 1917  interruption1(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
   // Récupération des signaux
   // - SIGFSTP
   //
   // ATTENTION :
   // Le signal SIGFSTP provient de la mort du processus de contrôle.
   // Sous certains systèmes (Linux...), la mort du terminal de contrôle
   // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
   // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
   // non initialisée (pointeur NULL) issue de TERMIO.
   
 void  void
 interruption2(SIGHANDLER_ARGS)  interruption2(int signal)
 {  {
     pid_t                   pid;      test_signal(signal);
       envoi_signal_processus(getpid(), rpl_sigtstp);
     pthread_t               thread;      return;
   }
   
     struct_processus        *s_etat_processus;  static inline void
   signal_tstp(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
 #   ifndef _BROKEN_SIGINFO  
     if (siginfo == NULL)  
     {  
         /*  
          * Le signal SIGFSTP provient de la mort du processus de contrôle.  
          * Sous certains systèmes (Linux...), la mort du terminal de contrôle  
          * se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres  
          * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo  
          * non initialisée (pointeur NULL) issue de TERMIO.  
          */  
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)  
         {  
             pthread_kill(thread, SIGHUP);  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
     }  
     else  
 #   endif  
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))  
                 == NULL)  
         {  
             deverrouillage_gestionnaire_signaux();  
             return;  
         }  
   
         /*          /*
          *  0 => fonctionnement normal           *  0 => fonctionnement normal
          * -1 => requête           * -1 => requête
Line 2444  interruption2(SIGHANDLER_ARGS) Line 1952  interruption2(SIGHANDLER_ARGS)
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
   
         if ((*s_etat_processus).var_volatile_processus_pere == 0)          if ((*s_etat_processus).var_volatile_processus_pere == 0)
         {          {
             kill((*s_etat_processus).pid_processus_pere, signal);              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigtstp);
         }          }
         else          else
         {          {
Line 2462  interruption2(SIGHANDLER_ARGS) Line 1971  interruption2(SIGHANDLER_ARGS)
     {      {
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, SIGTSTP);              envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
Line 2475  interruption2(SIGHANDLER_ARGS) Line 1983  interruption2(SIGHANDLER_ARGS)
 }  }
   
 void  void
 interruption3(SIGHANDLER_ARGS)  interruption3(int signal)
 {  {
     pid_t                   pid;      // 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.
   
     struct_processus        *s_etat_processus;      unsigned char       message[] = "+++System : Uncaught access violation\n"
                                   "+++System : Aborting !\n";
   
     static int              compteur = 0;      test_signal(signal);
   
     verrouillage_gestionnaire_signaux();      if (pid_processus_pere == getpid())
       {
           kill(pid_processus_pere, SIGALRM);
       }
   
 #   ifdef _BROKEN_SIGINFO      write(STDERR_FILENO, message, strlen(message));
     pid = origine_signal(signal);      _exit(EXIT_FAILURE);
 #   else  }
     pid = (*siginfo).si_pid;  
 #   endif  #if 0
   // Utiliser libsigsegv
   void INTERRUPTION3_A_FIXER()
   {
       pthread_t               thread;
   
       struct_processus        *s_etat_processus;
   
       test_signal(signal);
       verrouillage_gestionnaire_signaux();
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
Line 2515  interruption3(SIGHANDLER_ARGS) Line 2038  interruption3(SIGHANDLER_ARGS)
         // Segfault dans une routine interne          // Segfault dans une routine interne
         if (strncmp(getenv("LANG"), "fr", 2) == 0)          if (strncmp(getenv("LANG"), "fr", 2) == 0)
         {          {
             printf("+++Système : Violation d'accès (dépassement de pile)\n");              printf("+++Système : Violation d'accès\n");
         }          }
         else          else
         {          {
             printf("+++System : Access violation (stack overflow)\n");              printf("+++System : Access violation\n");
         }          }
   
         fflush(stdout);          fflush(stdout);
   
         compteur++;          (*s_etat_processus).compteur_violation_d_acces++;
   
         if (compteur > 1)          if ((*s_etat_processus).compteur_violation_d_acces > 1)
         {          {
               // 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
               // récupérable et on sort autoritairement du programme. Il peut
               // rester des processus orphelins en attente !
   
               if (strncmp(getenv("LANG"), "fr", 2) == 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);
   
             deverrouillage_gestionnaire_signaux();              deverrouillage_gestionnaire_signaux();
             exit(EXIT_FAILURE);              exit(EXIT_FAILURE);
         }          }
         else          else
         {          {
             deverrouillage_gestionnaire_signaux();              // Première erreur de segmentation. On essaie de terminer
             longjmp(contexte_initial, -1);              // proprement le thread ou le processus. Le signal ne peut être
         }              // envoyé que depuis le même processus.
     }  
   
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 void              if (recherche_thread_principal(getpid(), &thread) == d_vrai)
 interruption4(SIGHANDLER_ARGS)              {
 {                  if (pthread_equal(thread, pthread_self()) != 0)
     pid_t                   pid;                  {
                       deverrouillage_gestionnaire_signaux();
   
     struct_processus        *s_etat_processus;                      if ((*s_etat_processus).pid_processus_pere != getpid())
                       {
                           // On est dans le thread principal d'un processus.
   
     verrouillage_gestionnaire_signaux();                          longjmp(contexte_processus, -1);
                       }
                       else
                       {
                           // On est dans le thread principal du processus
                           // père.
   
 #   ifdef _BROKEN_SIGINFO                          longjmp(contexte_initial, -1);
     pid = origine_signal(signal);                      }
 #   else                  }
     pid = (*siginfo).si_pid;                  else
 #   endif                  {
                       // On est dans un thread fils d'un thread principal.
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)                      deverrouillage_gestionnaire_signaux();
     {                      longjmp(contexte_thread, -1);
         deverrouillage_gestionnaire_signaux();                  }
         return;              }
     }  
   
     /*              // Là, on ramasse les miettes puisque le thread n'existe plus
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)              // dans la base (corruption de la mémoire).
      */  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              deverrouillage_gestionnaire_signaux();
     {              longjmp(contexte_initial, -1);
         printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),          }
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux();
     return;      return;
 }  }
   #endif
   
 void  // Traitement de rpl_sigstart
 interruption5(SIGHANDLER_ARGS)  
   static inline void
   signal_start(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t                   pid;      (*s_etat_processus).demarrage_fils = d_vrai;
       return;
   }
   
     pthread_t               thread;  // Traitement de rpl_sigcont
   
     struct_processus        *s_etat_processus;  static inline void
   signal_cont(struct_processus *s_etat_processus, pid_t pid)
   {
       (*s_etat_processus).redemarrage_processus = d_vrai;
       return;
   }
   
     verrouillage_gestionnaire_signaux();  // Traitement de rpl_sigstop
   
 #   ifdef _BROKEN_SIGINFO  static inline void
     pid = origine_signal(signal);  signal_stop(struct_processus *s_etat_processus, pid_t pid)
 #   else  {
     pid = (*siginfo).si_pid;      struct_processus        *s_thread_principal;
 #   endif  
       verrouillage_gestionnaire_signaux();
   
     if (pid == getpid())      if (pid == getpid())
     {      {
Line 2606  interruption5(SIGHANDLER_ARGS) Line 2159  interruption5(SIGHANDLER_ARGS)
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGFSTOP (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
Line 2638  interruption5(SIGHANDLER_ARGS) Line 2191  interruption5(SIGHANDLER_ARGS)
   
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, signal);              envoi_signal_contexte(s_thread_principal, rpl_sigstop);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
Line 2650  interruption5(SIGHANDLER_ARGS) Line 2202  interruption5(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
 void  // Traitement de rpl_siginject
 interruption6(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
   static inline void
   signal_inject(struct_processus *s_etat_processus, pid_t pid)
   {
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          deverrouillage_gestionnaire_signaux();
Line 2673  interruption6(SIGHANDLER_ARGS) Line 2217  interruption6(SIGHANDLER_ARGS)
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
                 (unsigned long long) pthread_self());                  (unsigned long long) pthread_self());
         fflush(stdout);          fflush(stdout);
     }      }
Line 2682  interruption6(SIGHANDLER_ARGS) Line 2226  interruption6(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
   // Récupération des signaux
   // - SIGPIPE
   
 void  void
 interruption7(SIGHANDLER_ARGS)  interruption5(int signal)
 {  {
     pid_t                   pid;      unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO      test_signal(signal);
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  
     {  
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (pid_processus_pere == getpid())
     {      {
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),          envoi_signal_processus(pid_processus_pere, rpl_sigalrm);
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }      }
   
     (*s_etat_processus).var_volatile_requete_arret = -1;      write(STDERR_FILENO, message, strlen(message));
     deverrouillage_gestionnaire_signaux();  
   
     BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));  
     return;      return;
 }  }
   
 void  static inline void
 interruption8(SIGHANDLER_ARGS)  signal_urg(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t                   pid;      struct_processus        *s_thread_principal;
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
Line 2745  interruption8(SIGHANDLER_ARGS) Line 2264  interruption8(SIGHANDLER_ARGS)
   
         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),              printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
                     (unsigned long long) pthread_self());                      (unsigned long long) pthread_self());
             fflush(stdout);              fflush(stdout);
         }          }
Line 2757  interruption8(SIGHANDLER_ARGS) Line 2276  interruption8(SIGHANDLER_ARGS)
     {      {
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, SIGURG);              envoi_signal_contexte(s_thread_principal, rpl_sigurg);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
Line 2769  interruption8(SIGHANDLER_ARGS) Line 2287  interruption8(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigabort
 interruption9(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)  static inline void
     {  signal_abort(struct_processus *s_etat_processus, pid_t pid)
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
     {  
         printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }  
   
 #   ifdef _BROKEN_SIGINFO  
     if (queue_in(getpid(), signal) != 0)  
     {  
         return;  
     }  
   
     deverrouillage_gestionnaire_signaux();  
     interruption11(signal);  
 #   else  
     deverrouillage_gestionnaire_signaux();  
     interruption11(signal, siginfo, context);  
 #   endif  
     return;  
 }  
   
 void  
 interruption10(SIGHANDLER_ARGS)  
 {  {
     file                    *fichier;      struct_processus        *s_thread_principal;
   
     pid_t                   pid;  
   
     struct_processus        *s_etat_processus;  
   
     unsigned char           nom[8 + 64 + 1];  
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
     {      {
         deverrouillage_gestionnaire_signaux();          deverrouillage_gestionnaire_signaux();
         return;          return;
     }      }
   
     snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),  
             (unsigned long) pthread_self());  
   
     if ((fichier = fopen(nom, "w+")) != NULL)  
     {  
         fclose(fichier);  
   
         freopen(nom, "w", stdout);  
         freopen(nom, "w", stderr);  
     }  
   
     freopen("/dev/null", "r", stdin);  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
     {      {
         printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),          printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
                 (unsigned long long) pthread_self());                  (unsigned long long) pthread_self());
         fflush(stdout);          fflush(stdout);
     }      }
   
     deverrouillage_gestionnaire_signaux();  
     return;  
 }  
   
 void  
 interruption11(SIGHANDLER_ARGS)  
 {  
     pid_t                   pid;  
   
     pthread_t               thread;  
   
     struct_processus        *s_etat_processus;  
   
     verrouillage_gestionnaire_signaux();  
   
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     pid = (*siginfo).si_pid;  
 #   endif  
   
     if (pid == getpid())      if (pid == getpid())
     {      {
         if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))          if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
Line 2925  interruption11(SIGHANDLER_ARGS) Line 2356  interruption11(SIGHANDLER_ARGS)
   
         // Envoi d'un signal au thread maître du groupe.          // Envoi d'un signal au thread maître du groupe.
   
         if (recherche_thread_principal(getpid(), &thread) == d_vrai)          if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             pthread_kill(thread, signal);              envoi_signal_contexte(s_thread_principal, rpl_sigabort);
             deverrouillage_gestionnaire_signaux();  
             return;  
         }          }
     }      }
   
Line 2937  interruption11(SIGHANDLER_ARGS) Line 2367  interruption11(SIGHANDLER_ARGS)
     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
   signal_hup(struct_processus *s_etat_processus, pid_t pid)
   {
       file                    *fichier;
   
       unsigned char           nom[8 + 64 + 1];
   
       verrouillage_gestionnaire_signaux();
   
       if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
       {
           deverrouillage_gestionnaire_signaux();
           return;
       }
   
       snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),
               (unsigned long) pthread_self());
   
       if ((fichier = fopen(nom, "w+")) != NULL)
       {
           fclose(fichier);
   
           freopen(nom, "w", stdout);
           freopen(nom, "w", stderr);
       }
   
       freopen("/dev/null", "r", stdin);
   
       if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
       {
           printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),
                   (unsigned long long) pthread_self());
           fflush(stdout);
       }
   
       deverrouillage_gestionnaire_signaux();
       return;
   }
   
 void  void
 traitement_exceptions_gsl(const char *reason, const char *file,  traitement_exceptions_gsl(const char *reason, const char *file,
         int line, int gsl_errno)          int line, int gsl_errno)
Line 2956  traitement_exceptions_gsl(const char *re Line 2436  traitement_exceptions_gsl(const char *re
     return;      return;
 }  }
   
 #ifdef _BROKEN_SIGINFO  static inline void
   envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
           pid_t pid_source)
   {
       unsigned char       message[] = "+++System : Spurious signa !\n";
   
       switch(signal)
       {
           case rpl_sigint:
               signal_int(s_etat_processus, pid_source);
               break;
   
           case rpl_sigterm:
               signal_term(s_etat_processus, pid_source);
               break;
   
           case rpl_sigstart:
               signal_start(s_etat_processus, pid_source);
               break;
   
           case rpl_sigcont:
               signal_cont(s_etat_processus, pid_source);
               break;
   
           case rpl_sigstop:
               signal_stop(s_etat_processus, pid_source);
               break;
   
           case rpl_sigabort:
               signal_abort(s_etat_processus, pid_source);
               break;
   
           case rpl_sigurg:
               signal_urg(s_etat_processus, pid_source);
               break;
   
           case rpl_siginject:
               signal_inject(s_etat_processus, pid_source);
               break;
   
           case rpl_sigalrm:
               signal_alrm(s_etat_processus, pid_source);
               break;
   
           case rpl_sighup:
               signal_hup(s_etat_processus, pid_source);
               break;
   
           case rpl_sigtstp:
               signal_tstp(s_etat_processus, pid_source);
               break;
   
           default:
               write(STDERR_FILENO, message, strlen(message));
               break;
       }
   
       return;
   }
   
   void
   scrutation_interruptions(struct_processus *s_etat_processus)
   {
       // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
   
       // Interruptions qui arrivent depuis le groupe courant de threads.
   
 #undef kill      if ((*s_etat_processus).pointeur_signal_lecture !=
 #undef pthread_kill              (*s_etat_processus).pointeur_signal_ecriture)
       {
           // Il y a un signal dans la queue du thread courant. On le traite.
       }
   
       return;
   }
   
 int  int
 kill_broken_siginfo(pid_t pid, int signal)  envoi_signal_processus(pid_t pid, enum signaux_rpl signal)
 {  {
     int                 ios;      // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
       // mémoire puis d'y inscrire le signal à traiter.
   
     sem_t               *semaphore;      return(0);
   }
   
     unsigned char       *nom;  int
   envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
   {
       // Un signal est envoyé d'un thread à un autre thread du même processus.
   
       return(0);
   }
   
   int
   envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
           enum signaux_rpl signal)
   {
       (*s_etat_processus_a_signaler).signaux_en_queue
               [(*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1] =
               signal;
   
       // On valide l'écriture. Cela évite l'utilisation d'un mutex.
   
       (*s_etat_processus_a_signaler).pointeur_signal_ecriture++;
       return(0);
   }
   
   
   /*
   ================================================================================
     Fonction renvoyant le nom du segment de mémoire partagée en fonction
     du pid du processus.
   ================================================================================
     Entrée : Chemin absolue servant de racine, pid du processus
   --------------------------------------------------------------------------------
     Sortie : NULL ou nom du segment
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   static unsigned char *
   nom_segment(unsigned char *chemin, pid_t pid)
   {
       unsigned char               *fichier;
   
   #   ifdef IPCS_SYSV // !POSIX
   #       ifndef OS2 // !OS2
   
               if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) *
                       sizeof(unsigned char))) == NULL)
               {
                   return(NULL);
               }
   
               sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
   #       else // OS2
               if ((fichier = malloc((10 + 256 + 1) * sizeof(unsigned char)))
                       == NULL)
               {
                   return(NULL);
               }
   
               sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
   #       endif // OS2
   #   else // POSIX
   
           if ((fichier = malloc((1 + 256 + 1) *
                   sizeof(unsigned char))) == NULL)
           {
               return(NULL);
           }
   
           sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
   #   endif
   
       return(fichier);
   }
   
   
   /*
   ================================================================================
     Fonction créant un segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
     /*  void
      * Lorsqu'on veut interrompre le processus pid, on ouvre le segment  creation_queue_signaux(struct_processus *s_etat_processus)
      * correspondant au processus en question et ou ajoute le pid dans la  {
      * queue.      int                             segment;
      *  
      * Le sémaphore global à tous les threads d'un même processus sert  
      * à garantir que les signaux seront traités dans l'ordre de ce qui est  
      * effectivement mis dans la queue.  
      */  
   
     // Sémaphore acquis      pthread_mutexattr_t             attributs_mutex;
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)      unsigned char                   *nom;
   
   #   ifndef IPCS_SYSV // POSIX
   
       if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
               getpid())) == NULL)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
               S_IRUSR | S_IWUSR)) == -1)
     {      {
         free(nom);          free(nom);
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if (ftruncate(segment, sizeof(struct_queue_signaux)) == -1)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
               PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0);
       close(segment);
   
       if (((void *) s_queue_signaux) == ((void *) -1))
       {
           if (shm_unlink(nom) == -1)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       free(nom);
   
       pthread_mutexattr_init(&attributs_mutex);
       pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_NORMAL);
       pthread_mutex_init(&((*s_queue_signaux).mutex), &attributs_mutex);
       pthread_mutexattr_destroy(&attributs_mutex);
   
       (*s_queue_signaux).pointeur_lecture = 0;
       (*s_queue_signaux).pointeur_ecriture = 0;
   
   #   else // SystemV
   #   ifndef OS2
   
       file                            *desc;
   
       key_t                           clef;
   
       // 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 ((desc = fopen(nom, "w")) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
           return;
       }
   
       fclose(desc);
   
       if ((clef = ftok(nom, 1)) == -1)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     free(nom);      free(nom);
   
     if (sem_wait(semaphore) == -1)      if ((segment = shmget(clef,
               nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
               IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     if ((signal != 0) && (signal != SIGINT))      fifos = shmat(segment, NULL, 0);
   
       if (((void *) fifos) == ((void *) -1))
     {      {
         if (queue_in(pid, signal) != 0)          if (shmctl(segment, IPC_RMID, 0) == -1)
         {          {
             sem_post(semaphore);              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             sem_close(semaphore);              return;
             return(-1);  
         }          }
   
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     ios = kill(pid, signal);  #   else
   
     // Sémaphore relâché      if ((nom = nom_segment(NULL, getpid())) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if (DosAllocSharedMem(&ptr_os2, nom, nombre_queues *
               ((2 * longueur_queue) + 4) * sizeof(int),
               PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
     sem_post(semaphore);      free(nom);
     sem_close(semaphore);      fifos = ptr_os2;
   
     return(ios);  #   endif
   #   endif
   
       return;
 }  }
   
 int  
 pthread_kill_broken_siginfo(pthread_t tid, int signal)  /*
   ================================================================================
     Fonction libérant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   void
   liberation_queue_signaux(struct_processus *s_etat_processus)
 {  {
     int                 ios;  #   ifdef IPCS_SYSV // SystemV
   #       ifndef OS2
   #       else // OS/2
   #       endif
   #   else // POSIX
           if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   #   endif
   
       return;
   }
   
     sem_t               *semaphore;  
   
   /*
   ================================================================================
     Fonction détruisant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   void
   destruction_queue_signaux(struct_processus *s_etat_processus)
   {
     unsigned char       *nom;      unsigned char       *nom;
   
     if ((nom = nom_semaphore(getpid(), nombre_queues)) == NULL)  #   ifdef IPCS_SYSV // SystemV
   #   ifndef OS2
   
       if (shmdt(fifos) == -1)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      if (shmctl(segment, IPC_RMID, 0) == -1)
     {      {
         free(nom);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return(-1);          return;
     }      }
   
       if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
               getpid())) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       unlink(nom);
     free(nom);      free(nom);
   
     if (sem_wait(semaphore) == -1)  #   else
   
       if (DosFreeMem(fifos) != 0)
     {      {
         return(-1);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     if ((signal != 0) && (signal != SIGINT))  #   endif
   #   else // POSIX
   
       if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
     {      {
         if (queue_in(getpid(), signal) != 0)          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         {          return;
             sem_post(semaphore);      }
             sem_close(semaphore);  
             return(-1);      if ((nom = nom_segment(NULL, getpid())) == NULL)
         }      {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if (shm_unlink(nom) != 0)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
     }      }
   
     ios = pthread_kill(tid, signal);      free(nom);
   
     sem_post(semaphore);  #   endif
     sem_close(semaphore);  
   
     return(ios);      return;
 }  }
   
 #endif  
   
 // vim: ts=4  // vim: ts=4

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


CVSweb interface <joel.bertrand@systella.fr>