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

version 1.66, 2011/09/10 20:45:06 version 1.67, 2011/09/14 14:34:28
Line 1718  deverrouillage_gestionnaire_signaux() Line 1718  deverrouillage_gestionnaire_signaux()
 }  }
   
 #define test_signal(signal) \  #define test_signal(signal) \
     if (signal_test == SIGTEST) \      if (signal_test == SIGTEST) { signal_test = signal; return; }
     { signal_test = initialisation_queue_interruptions(signal); return; }  
   
 /*  // Récupération des signaux
  * Les interruptions sont mise en mémoire puis traitées depuis  // - SIGINT (arrêt au clavier)
  * la fonction scrutation_injection() parce que les fonctions pthread*()  // - SIGTERM (signal d'arrêt en provenance du système)
  * ne sont pas 'async signal safe'.  
  *  
  * Les interruptions sont ainsi empilées dans un buffer circulaire puis  
  * traitées au fur et à mesure.  
  */  
   
 static struct  
 {  
 #   define                  SIGNAL_MAX      32  
 #   define                  SIGNAL_BUFFER   1024  
 #   define                  ECRITURE        0  
 #   define                  LECTURE         1  
   
     sig_atomic_t            nombre_interruptions_en_queue;  
     int                     pointeur[SIGNAL_MAX][2];  
   
     pid_t                   pid[SIGNAL_MAX][SIGNAL_BUFFER];  
 } queue_interruptions;  
   
 pthread_mutex_t             mutex_signal = PTHREAD_MUTEX_INITIALIZER;  void
   interruption1(int signal)
 static inline int  
 initialisation_queue_interruptions(int signal)  
 {  {
     int         i;      test_signal(signal);
   
     if (signal > SIGNAL_MAX)      switch(signal)
     {      {
         return(signal + 1);          case SIGINT:
     }              envoi_signal_processus(getpid(), rpl_sigint);
               break;
   
     queue_interruptions.nombre_interruptions_en_queue = 0;          case SIGTERM:
               envoi_signal_processus(getpid(), rpl_sigterm);
               break;
   
     for(i = 0; i < SIGNAL_MAX; i++)          case SIGALRM:
     {              envoi_signal_processus(getpid(), rpl_sigalrm);
         queue_interruptions.pointeur[i][ECRITURE] = 0;              break;
         queue_interruptions.pointeur[i][LECTURE] = 0;  
     }      }
   
     return(signal);      return;
 }  }
   
 void  inline static void
 interruption1(SIGHANDLER_ARGS)  signal_alrm(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t               pid;      struct_processus        *s_thread_principal;
   
     test_signal(signal);      verrouillage_gestionnaire_signaux();
   
 #   ifdef _BROKEN_SIGINFO      if (pid == getpid())
         if ((signal == SIGINT) || (signal == SIGTERM))      {
         {          // Si pid est égal à getpid(), le signal à traiter est issu
             // Si l'interruption provient du clavier, il n'y a pas eu d'appel          // du même processus que celui qui va le traiter, mais d'un thread
             // à queue_in().          // différent.
   
             pid = getpid();          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         }  
         else  
         {          {
             pid = origine_signal(signal);              printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
                       (unsigned long long) pthread_self());
               fflush(stdout);
         }          }
 #   else  
   
     /*  
      * Une vieille spécification POSIX permet au pointeur siginfo  
      * d'être nul dans le cas d'un ^C envoyé depuis le clavier.  
      * Solaris suit en particulier cette spécification.  
      */  
   
         if (siginfo != NULL)          if ((*s_etat_processus).pid_processus_pere != getpid())
         {          {
             pid = (*siginfo).si_pid;              // On n'est pas dans le processus père, on remonte le signal.
               envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                       rpl_sigalrm);
         }          }
         else          else
         {          {
             pid = getpid();              // On est dans le processus père, on effectue un arrêt d'urgence.
               (*s_etat_processus).var_volatile_alarme = -1;
               (*s_etat_processus).var_volatile_requete_arret = -1;
         }          }
 #   endif      }
       else
       {
           // Le signal est issu d'un processus différent. On recherche le
           // thread principal pour remonter le signal.
   
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
           {
               envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
           }
       }
   
     queue_interruptions.pid[signal][queue_interruptions.pointeur      deverrouillage_gestionnaire_signaux();
             [signal][ECRITURE]] = pid;  
     queue_interruptions.pointeur[signal][ECRITURE] =  
             (queue_interruptions.pointeur[signal][ECRITURE] + 1)  
             % SIGNAL_BUFFER;  
     queue_interruptions.nombre_interruptions_en_queue++;  
     return;      return;
 }  }
   
 static void  inline static void
 corps_interruption1(struct_processus *s_etat_processus, int signal, pid_t pid)  signal_term(struct_processus *s_etat_processus, pid_t pid)
 {  {
     volatile sig_atomic_t   exclusion = 0;  
   
     struct_processus        *s_thread_principal;      struct_processus        *s_thread_principal;
       volatile sig_atomic_t   exclusion = 0;
   
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
     switch(signal)      if (pid == getpid())
     {      {
         case SIGALRM :          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
         {          {
             if (pid == getpid())              printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
             {                      (unsigned long long) pthread_self());
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)              fflush(stdout);
                 {          }
                     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).pid_processus_pere != getpid())
                 {          {
                     kill((*s_etat_processus).pid_processus_pere, signal);              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                 }                      rpl_sigterm);
                 else          }
                 {          else
                     (*s_etat_processus).var_volatile_alarme = -1;          {
                     (*s_etat_processus).var_volatile_requete_arret = -1;              (*s_etat_processus).var_volatile_traitement_sigint = -1;
                 }  
             }              while(exclusion == 1);
             else              exclusion = 1;
   
               if ((*s_etat_processus).var_volatile_requete_arret == -1)
             {              {
                 if ((s_thread_principal = recherche_thread_principal(getpid()))                  deverrouillage_gestionnaire_signaux();
                         != NULL)                  exclusion = 0;
                 {                  return;
                     while((*s_etat_processus).signal_a_traiter == d_vrai);  
                     (*s_etat_processus).signal = signal;  
                     (*s_etat_processus).origine_signal = getpid();  
                     (*s_etat_processus).signal_a_traiter = d_vrai;  
                 }  
             }              }
   
             break;              (*s_etat_processus).var_volatile_requete_arret = -1;
         }              (*s_etat_processus).var_volatile_alarme = -1;
   
         case SIGINT :              exclusion = 0;
         case SIGTERM :          }
       }
       else
       {
           if ((s_thread_principal = recherche_thread_principal(getpid()))
                   != NULL)
         {          {
             if (pid == getpid())              envoi_signal_contexte(s_thread_principal, rpl_sigterm);
             {          }
                 if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      }
                 {  
                     if (signal == SIGINT)  
                     {  
                         printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),  
                                 (unsigned long long) pthread_self());  
                     }  
                     else  
                     {  
                         printf("[%d] SIGTERM (thread %llu)\n", (int) getpid(),  
                                 (unsigned long long) pthread_self());  
                     }  
   
                     fflush(stdout);      deverrouillage_gestionnaire_signaux();
                 }      return;
   }
   
                 if ((*s_etat_processus).pid_processus_pere != getpid())  inline static void
                 {  signal_int(struct_processus *s_etat_processus, pid_t pid)
                     kill((*s_etat_processus).pid_processus_pere, signal);  {
                 }      struct_processus        *s_thread_principal;
                 else      volatile sig_atomic_t   exclusion = 0;
                 {  
                     (*s_etat_processus).var_volatile_traitement_sigint = -1;  
   
                     while(exclusion == 1);      verrouillage_gestionnaire_signaux();
                     exclusion = 1;  
   
                     if ((*s_etat_processus).var_volatile_requete_arret == -1)      if (pid == getpid())
                     {      {
                         deverrouillage_gestionnaire_signaux();          if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
                         exclusion = 0;          {
                         return;              printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
                     }                      (unsigned long long) pthread_self());
               fflush(stdout);
           }
   
                     if (signal == SIGINT)          if ((*s_etat_processus).pid_processus_pere != getpid())
                     {          {
                         if (strncmp(getenv("LANG"), "fr", 2) == 0)              envoi_signal_processus((*s_etat_processus).pid_processus_pere,
                         {                      rpl_sigint);
                             printf("+++Interruption\n");          }
                         }          else
                         else          {
                         {              (*s_etat_processus).var_volatile_traitement_sigint = -1;
                             printf("+++Interrupt\n");  
                         }  
   
                         fflush(stdout);              while(exclusion == 1);
                     }              exclusion = 1;
   
                     (*s_etat_processus).var_volatile_requete_arret = -1;              if ((*s_etat_processus).var_volatile_requete_arret == -1)
                     (*s_etat_processus).var_volatile_alarme = -1;              {
                   deverrouillage_gestionnaire_signaux();
                   exclusion = 0;
                   return;
               }
   
                     exclusion = 0;              if ((*s_etat_processus).langue == 'F')
                 }              {
                   printf("+++Interruption\n");
             }              }
             else              else
             {              {
                 if ((s_thread_principal = recherche_thread_principal(getpid()))                  printf("+++Interrupt\n");
                         != NULL)  
                 {  
                     while((*s_etat_processus).signal_a_traiter == d_vrai);  
                     (*s_etat_processus).signal = signal;  
                     (*s_etat_processus).origine_signal = getpid();  
                     (*s_etat_processus).signal_a_traiter = d_vrai;  
                 }  
             }              }
   
             break;              fflush(stdout);
         }  
               (*s_etat_processus).var_volatile_requete_arret = -1;
               (*s_etat_processus).var_volatile_alarme = -1;
   
         default :              exclusion = 0;
           }
       }
       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 1945  corps_interruption1(struct_processus *s_ Line 1917  corps_interruption1(struct_processus *s_
     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);      test_signal(signal);
       envoi_signal_processus(getpid(), rpl_sigtstp);
 #   ifdef _BROKEN_SIGINFO  
     pid = origine_signal(signal);  
 #   else  
     if (siginfo != NULL)  
     {  
         pid = (*siginfo).si_pid;  
     }  
     else  
     {  
         pid = getpid();  
     }  
 #   endif  
   
     queue_interruptions.pid[signal][queue_interruptions.pointeur  
             [signal][ECRITURE]] = pid;  
     queue_interruptions.pointeur[signal][ECRITURE] =  
             (queue_interruptions.pointeur[signal][ECRITURE] + 1)  
             % SIGNAL_BUFFER;  
   
     /*  
      * 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 (siginfo == NULL)  
     {  
         queue_interruptions.pid[SIGHUP][queue_interruptions.pointeur  
                 [SIGHUP][ECRITURE]] = pid;  
         queue_interruptions.pointeur[SIGHUP][ECRITURE] =  
                 (queue_interruptions.pointeur[SIGHUP][ECRITURE] + 1)  
                 % SIGNAL_BUFFER;  
         queue_interruptions.nombre_interruptions_en_queue += 2;  
     }  
   
     return;      return;
 }  }
   
 static void  static inline void
 corps_interruption2(struct_processus *s_etat_processus, int signal, pid_t pid)  signal_tstp(struct_processus *s_etat_processus, pid_t pid)
 {  {
     struct_processus        *s_thread_principal;      struct_processus        *s_thread_principal;
   
Line 2009  corps_interruption2(struct_processus *s_ Line 1952  corps_interruption2(struct_processus *s_
   
         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 2030  corps_interruption2(struct_processus *s_ Line 1974  corps_interruption2(struct_processus *s_
         if ((s_thread_principal = recherche_thread_principal(getpid()))          if ((s_thread_principal = recherche_thread_principal(getpid()))
                 != NULL)                  != NULL)
         {          {
             while((*s_etat_processus).signal_a_traiter == d_vrai);              envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
             (*s_etat_processus).signal = signal;  
             (*s_etat_processus).origine_signal = getpid();  
             (*s_etat_processus).signal_a_traiter = d_vrai;  
         }          }
     }      }
   
Line 2042  corps_interruption2(struct_processus *s_ Line 1983  corps_interruption2(struct_processus *s_
 }  }
   
 void  void
 interruption3(SIGHANDLER_ARGS)  interruption3(int signal)
 {  {
     // Si on passe par ici, c'est qu'il est impossible de récupérer      // 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 à      // l'erreur d'accès à la mémoire. On sort donc du programme quitte à
     // ce qu'il reste des processus orphelins.      // ce qu'il reste des processus orphelins.
   
     unsigned char       message[] = "+++System : Uncaught access violation\n"      unsigned char       message[] = "+++System : Uncaught access violation\n"
                                 "+++System : Aborting !\n;                                  "+++System : Aborting !\n";
   
       test_signal(signal);
   
     if (pid_processus_pere == getpid())      if (pid_processus_pere == getpid())
     {      {
Line 2060  interruption3(SIGHANDLER_ARGS) Line 2003  interruption3(SIGHANDLER_ARGS)
     _exit(EXIT_FAILURE);      _exit(EXIT_FAILURE);
 }  }
   
   #if 0
   // Utiliser libsigsegv
 void INTERRUPTION3_A_FIXER()  void INTERRUPTION3_A_FIXER()
 {  {
     pthread_t               thread;      pthread_t               thread;
Line 2174  void INTERRUPTION3_A_FIXER() Line 2119  void INTERRUPTION3_A_FIXER()
     deverrouillage_gestionnaire_signaux();      deverrouillage_gestionnaire_signaux();
     return;      return;
 }  }
   #endif
   
 void  // Traitement de rpl_sigstart
 interruption4(SIGHANDLER_ARGS)  
 {  
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  static inline void
     verrouillage_gestionnaire_signaux();  signal_start(struct_processus *s_etat_processus, pid_t pid)
   {
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      (*s_etat_processus).demarrage_fils = d_vrai;
     {  
         deverrouillage_gestionnaire_signaux();  
         return;  
     }  
   
     /*  
      * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)  
      */  
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)  
     {  
         printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }  
   
     deverrouillage_gestionnaire_signaux();  
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigcont
 interruption5(SIGHANDLER_ARGS)  
   static inline void
   signal_cont(struct_processus *s_etat_processus, pid_t pid)
 {  {
     pid_t                   pid;      (*s_etat_processus).redemarrage_processus = d_vrai;
       return;
   }
   
     pthread_t               thread;  // Traitement de rpl_sigstop
   
     struct_processus        *s_etat_processus;  static inline void
   signal_stop(struct_processus *s_etat_processus, pid_t pid)
   {
       struct_processus        *s_thread_principal;
   
     test_signal(signal);  
     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 2233  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 2265  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 2277  interruption5(SIGHANDLER_ARGS) Line 2202  interruption5(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
 void  // Traitement de rpl_siginject
 interruption6(SIGHANDLER_ARGS)  
 {  
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  static inline void
   signal_inject(struct_processus *s_etat_processus, pid_t pid)
   {
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
Line 2293  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 2302  interruption6(SIGHANDLER_ARGS) Line 2226  interruption6(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
   // Récupération des signaux
   // - SIGPIPE
   
 void  void
 interruption7(SIGHANDLER_ARGS)  interruption5(int signal)
 {  {
     struct_processus        *s_etat_processus;      unsigned char       message[] = "+++System : SIGPIPE\n"
                                   "+++System : Aborting !\n";
   
     test_signal(signal);      test_signal(signal);
     verrouillage_gestionnaire_signaux();  
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if (pid_processus_pere == getpid())
     {      {
         deverrouillage_gestionnaire_signaux();          envoi_signal_processus(pid_processus_pere, rpl_sigalrm);
         return;  
     }      }
   
     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)      write(STDERR_FILENO, message, strlen(message));
     {  
         printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),  
                 (unsigned long long) pthread_self());  
         fflush(stdout);  
     }  
   
     (*s_etat_processus).var_volatile_requete_arret = -1;  
     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;  
   
     test_signal(signal);  
     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 2359  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 2371  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 2383  interruption8(SIGHANDLER_ARGS) Line 2287  interruption8(SIGHANDLER_ARGS)
     return;      return;
 }  }
   
 void  // Traitement de rpl_sigabort
 interruption9(SIGHANDLER_ARGS)  
 {  
     struct_processus        *s_etat_processus;  
   
     test_signal(signal);  
     verrouillage_gestionnaire_signaux();  
   
     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;
   
     struct_processus        *s_etat_processus;  
   
     unsigned char           nom[8 + 64 + 1];  
   
     test_signal(signal);  
     verrouillage_gestionnaire_signaux();      verrouillage_gestionnaire_signaux();
   
     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)      if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
Line 2437  interruption10(SIGHANDLER_ARGS) Line 2302  interruption10(SIGHANDLER_ARGS)
         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;  
   
     test_signal(signal);  
     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 2526  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 2538  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 2558  traitement_exceptions_gsl(const char *re Line 2437  traitement_exceptions_gsl(const char *re
 }  }
   
 static inline void  static inline void
 structation_interruptions_elementaires(struct_processus *s_etat_processus,  envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
         int signal, pid_t pid)          pid_t pid_source)
 {  {
       unsigned char       message[] = "+++System : Spurious signa !\n";
   
     switch(signal)      switch(signal)
     {      {
         case SIGINT:          case rpl_sigint:
         case SIGTERM:              signal_int(s_etat_processus, pid_source);
         case SIGALRM:  
         {  
             corps_interruption1(s_etat_processus, signal, pid);  
             break;              break;
         }  
   
         case SIGTSTP:          case rpl_sigterm:
         {              signal_term(s_etat_processus, pid_source);
             corps_interruption2(s_etat_processus, signal, pid);              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;      return;
Line 2583  structation_interruptions_elementaires(s Line 2499  structation_interruptions_elementaires(s
 void  void
 scrutation_interruptions(struct_processus *s_etat_processus)  scrutation_interruptions(struct_processus *s_etat_processus)
 {  {
     int             i;      // Interruptions qui arrivent sur le processus depuis un
       // processus externe.
   
     // Interruption par processus.      // Interruptions qui arrivent depuis le groupe courant de threads.
   
     if (pthread_mutex_lock(&mutex_signal) != 0)      if ((*s_etat_processus).pointeur_signal_lecture !=
               (*s_etat_processus).pointeur_signal_ecriture)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          // Il y a un signal dans la queue du thread courant. On le traite.
       }
   
       return;
   }
   
   int
   envoi_signal_processus(pid_t pid, enum signaux_rpl signal)
   {
       // 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.
   
       return(0);
   }
   
   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
   creation_queue_signaux(struct_processus *s_etat_processus)
   {
       int                             segment;
   
       pthread_mutexattr_t             attributs_mutex;
   
       unsigned char                   *nom;
   
   #   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;          return;
     }      }
   
     if (queue_interruptions.nombre_interruptions_en_queue > 0)      if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
               S_IRUSR | S_IWUSR)) == -1)
     {      {
         for(i = 0; i < SIGNAL_MAX; i++)          free(nom);
           (*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)
         {          {
             if ((queue_interruptions.pointeur[i][ECRITURE] -              free(nom);
                     queue_interruptions.pointeur[i][LECTURE]) != 0)              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             {              return;
                 // Il y a une interruption dans la queue.          }
   
                 queue_interruptions.nombre_interruptions_en_queue--;          free(nom);
                 scrutation_interruptions_elementaires(s_etat_processus, i,          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                         queue_interruptions.pid[signal]          return;
                         [queue_interruptions.pointeur[signal][LECTURE]]);      }
                 queue_interruptions.pointeur[signal][LECTURE] =  
                         (queue_interruptions.pointeur[signal][LECTURE] + 1)      free(nom);
                         % SIGNAL_BUFFER;  
             }      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);
   
       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;
           return;
       }
   
       fifos = shmat(segment, NULL, 0);
   
       if (((void *) fifos) == ((void *) -1))
       {
           if (shmctl(segment, 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 (pthread_mutex_unlock(&mutex_signal) != 0)  #   else
   
       if ((nom = nom_segment(NULL, getpid())) == NULL)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_processus;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
   
     // Interruption par thread      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;
       }
   
       free(nom);
       fifos = ptr_os2;
   
   #   endif
   #   endif
   
       return;
   }
   
   
   /*
   ================================================================================
     Fonction libérant le segment de mémoire partagée destiné à contenir
     la queue des signaux.
   ================================================================================
     Entrée : structure de description du processus
   --------------------------------------------------------------------------------
     Sortie : Néant
   --------------------------------------------------------------------------------
     Effet de bord : Néant
   ================================================================================
   */
   
   void
   liberation_queue_signaux(struct_processus *s_etat_processus)
   {
   #   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;
   }
   
   
   /*
   ================================================================================
     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;
   
   #   ifdef IPCS_SYSV // SystemV
   #   ifndef OS2
   
     if ((*s_etat_processus).signal_a_traiter == d_vrai)      if (shmdt(fifos) == -1)
     {      {
         (*s_etat_processus).signal_a_traiter = d_faux;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         scrutation_interruptions_elementaires(s_etat_processus,          return;
                 (*s_etat_processus).signal, (*s_etat_processus).origine_signal);      }
   
       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);
       free(nom);
   
   #   else
   
       if (DosFreeMem(fifos) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
   #   endif
   #   else // POSIX
   
       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;
       }
   
       if (shm_unlink(nom) != 0)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       free(nom);
   
   #   endif
   
     return;      return;
 }  }
   

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


CVSweb interface <joel.bertrand@systella.fr>