File:  [local] / rpl / src / interruptions.c
Revision 1.177: download - view: text, annotated - select for diffs - revision graph
Fri Apr 1 11:26:21 2016 UTC (8 years ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction d'une race condition.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.25
    4:   Copyright (C) 1989-2016 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl-conv.h"
   24: 
   25: 
   26: /*
   27: ================================================================================
   28:   Procédures de gestion par thread des variables issues des gestionnaires
   29:   de signaux
   30: ================================================================================
   31:   Entrée : variable globale
   32: --------------------------------------------------------------------------------
   33:   Sortie : variable globale modifiée
   34: --------------------------------------------------------------------------------
   35:   Effets de bord : néant
   36: ================================================================================
   37: */
   38: 
   39: typedef struct thread
   40: {
   41:     pid_t               pid;
   42:     pthread_t           tid;
   43: 
   44:     logical1            thread_principal;
   45: 
   46:     struct_processus    *s_etat_processus;
   47: } struct_thread;
   48: 
   49: typedef struct liste_chainee_volatile
   50: {
   51:     volatile struct liste_chainee_volatile  *suivant;
   52:     volatile void                           *donnee;
   53: } struct_liste_chainee_volatile;
   54: 
   55: static volatile struct_liste_chainee_volatile   *liste_threads
   56:         = NULL;
   57: static volatile struct_liste_chainee_volatile   *liste_threads_surveillance
   58:         = NULL;
   59: static volatile int                             code_erreur_gsl = 0;
   60: 
   61: unsigned char                                   *racine_segment;
   62: 
   63: static void *
   64: thread_surveillance_signaux(void *argument)
   65: {
   66:     // Cette fonction est lancée dans un thread créé par processus pour
   67:     // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du
   68:     // signal SIGALRM. Les processus externes n'envoient plus un signal au
   69:     // processus ou au thread à signaler mais positionnent les informations
   70:     // nécessaires dans la queue des signaux et incrémentent le sémaphore.
   71:     // Le sémaphore est décrémenté lorsque le signal est effectivement traité.
   72: 
   73:     int                                     ios;
   74:     int                                     nombre_signaux_envoyes;
   75: 
   76:     struct_processus                        *s_etat_processus;
   77: 
   78:     struct timespec                         attente;
   79: 
   80:     volatile struct_liste_chainee_volatile  *l_element_courant;
   81: 
   82:     sigset_t                                set;
   83: 
   84:     sigfillset(&set);
   85:     pthread_sigmask(SIG_BLOCK, &set, NULL);
   86: 
   87:     s_etat_processus = (struct_processus *) argument;
   88: 
   89:     for(;;)
   90:     {
   91:         attente.tv_sec = 0;
   92:         attente.tv_nsec = GRANULARITE_us * 1000;
   93: 
   94:         if (sem_wait(semaphore_signalisation) == 0)
   95:         {
   96:             if (sem_wait(semaphore_arret_signalisation) != 0)
   97:             {
   98:                 (*s_etat_processus).erreur_systeme = d_es_processus;
   99:             }
  100: 
  101:             if ((*s_queue_signaux).requete_arret == d_vrai)
  102:             {
  103:                 sem_post(semaphore_arret_signalisation);
  104:                 sem_post(semaphore_signalisation);
  105: 
  106:                 break;
  107:             }
  108: 
  109:             sem_post(semaphore_arret_signalisation);
  110:             sem_post(semaphore_signalisation);
  111: 
  112:             nombre_signaux_envoyes = 0;
  113: 
  114:             // Dans un premier temps, on verrouille la queue des signaux
  115:             // affectée au processus courant pour vérifier s'il y a quelque
  116:             // chose à traiter.
  117: 
  118:             while((ios = sem_wait(semaphore_queue_signaux)) != 0)
  119:             {
  120:                 if (errno != EINTR)
  121:                 {
  122:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  123:                 }
  124:             }
  125: 
  126:             if ((*s_queue_signaux).pointeur_lecture !=
  127:                     (*s_queue_signaux).pointeur_ecriture)
  128:             {
  129:                 // Attention : raise() envoit le signal au thread appelant !
  130:                 // kill() l'envoie au processus appelant, donc dans notre
  131:                 // cas à un thread aléatoire du processus, ce qui nous
  132:                 // convient tout à fait puisqu'il s'agit de débloquer les
  133:                 // appels système lents.
  134: 
  135:                 nombre_signaux_envoyes++;
  136:                 kill(getpid(), SIGALRM);
  137:                 sched_yield();
  138:             }
  139: 
  140:             sem_post(semaphore_queue_signaux);
  141: 
  142:             // Dans un second temps, on balaye toutes les queues de signaux
  143:             // des threads du processus courant.
  144: 
  145:             // Attention : l'ordre de verrouillage des mutexes est important
  146:             // pour éviter les conditions bloquantes !
  147: 
  148:             pthread_mutex_lock(&mutex_liste_threads);
  149: 
  150:             l_element_courant = liste_threads;
  151: 
  152:             while(l_element_courant != NULL)
  153:             {
  154:                 if ((*((struct_thread *) (*l_element_courant).donnee)).pid
  155:                         == getpid())
  156:                 {
  157:                     pthread_mutex_lock(&((*(*((struct_thread *)
  158:                             (*l_element_courant).donnee)).s_etat_processus)
  159:                             .mutex_signaux));
  160: 
  161:                     if ((*(*((struct_thread *) (*l_element_courant).donnee))
  162:                             .s_etat_processus).pointeur_signal_ecriture !=
  163:                             (*(*((struct_thread *) (*l_element_courant)
  164:                             .donnee)).s_etat_processus).pointeur_signal_lecture)
  165:                     {
  166:                         nombre_signaux_envoyes++;
  167:                         pthread_kill((*((struct_thread *)
  168:                                 (*l_element_courant).donnee)).tid, SIGALRM);
  169:                         sched_yield();
  170:                     }
  171: 
  172:                     pthread_mutex_unlock(&((*(*((struct_thread *)
  173:                             (*l_element_courant).donnee)).s_etat_processus)
  174:                             .mutex_signaux));
  175:                 }
  176: 
  177:                 l_element_courant = (*l_element_courant).suivant;
  178:             }
  179: 
  180:             pthread_mutex_unlock(&mutex_liste_threads);
  181: 
  182:             // Nanosleep
  183: 
  184:             if (nombre_signaux_envoyes > 0)
  185:             {
  186:                 nanosleep(&attente, NULL);
  187:             }
  188:         }
  189:         else
  190:         {
  191:             if (errno != EINTR)
  192:             {
  193:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  194:             }
  195:         }
  196:     }
  197: 
  198:     pthread_exit(NULL);
  199: }
  200: 
  201: void
  202: modification_pid_thread_pere(struct_processus *s_etat_processus)
  203: {
  204:     // La variable existe toujours et aucun thread concurrent ne peut
  205:     // la modifier puisque cette routine ne peut être appelée que depuis
  206:     // DAEMON.
  207: 
  208:     (*((struct_thread *) (*liste_threads).donnee)).pid =
  209:             (*s_etat_processus).pid_processus_pere;
  210: 
  211:     return;
  212: }
  213: 
  214: void
  215: insertion_thread(struct_processus *s_etat_processus, logical1 thread_principal)
  216: {
  217:     volatile struct_liste_chainee_volatile      *l_nouvel_objet;
  218: 
  219:     if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
  220:             == NULL)
  221:     {
  222:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  223:         return;
  224:     }
  225: 
  226:     if (((*l_nouvel_objet).donnee = malloc(sizeof(struct_thread))) == NULL)
  227:     {
  228:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  229:         return;
  230:     }
  231: 
  232:     (*((struct_thread *) (*l_nouvel_objet).donnee)).pid = getpid();
  233:     (*((struct_thread *) (*l_nouvel_objet).donnee)).tid = pthread_self();
  234:     (*((struct_thread *) (*l_nouvel_objet).donnee)).thread_principal =
  235:             thread_principal;
  236:     (*((struct_thread *) (*l_nouvel_objet).donnee)).s_etat_processus =
  237:             s_etat_processus;
  238: 
  239:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
  240:     {
  241:         (*s_etat_processus).erreur_systeme = d_es_processus;
  242:         return;
  243:     }
  244: 
  245:     (*l_nouvel_objet).suivant = liste_threads;
  246:     liste_threads = l_nouvel_objet;
  247: 
  248:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  249:     {
  250:         (*s_etat_processus).erreur_systeme = d_es_processus;
  251:         return;
  252:     }
  253: 
  254:     return;
  255: }
  256: 
  257: void
  258: insertion_thread_surveillance(struct_processus *s_etat_processus,
  259:         struct_descripteur_thread *s_argument_thread)
  260: {
  261:     volatile struct_liste_chainee_volatile      *l_nouvel_objet;
  262: 
  263:     if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
  264:             == NULL)
  265:     {
  266:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  267:         return;
  268:     }
  269: 
  270:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
  271:     {
  272:         (*s_etat_processus).erreur_systeme = d_es_processus;
  273:         return;
  274:     }
  275: 
  276:     pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references));
  277:     (*s_argument_thread).nombre_references++;
  278:     pthread_mutex_unlock(&((*s_argument_thread).mutex_nombre_references));
  279: 
  280:     (*l_nouvel_objet).suivant = liste_threads_surveillance;
  281:     (*l_nouvel_objet).donnee = (void *) s_argument_thread;
  282: 
  283:     liste_threads_surveillance = l_nouvel_objet;
  284: 
  285:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  286:     {
  287:         (*s_etat_processus).erreur_systeme = d_es_processus;
  288:         return;
  289:     }
  290: 
  291:     return;
  292: }
  293: 
  294: void
  295: retrait_thread(struct_processus *s_etat_processus)
  296: {
  297:     volatile struct_liste_chainee_volatile  *l_element_precedent;
  298:     volatile struct_liste_chainee_volatile  *l_element_courant;
  299: 
  300:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
  301:     {
  302:         (*s_etat_processus).erreur_systeme = d_es_processus;
  303:         return;
  304:     }
  305: 
  306:     l_element_precedent = NULL;
  307:     l_element_courant = liste_threads;
  308: 
  309:     while(l_element_courant != NULL)
  310:     {
  311:         if (((*((struct_thread *) (*l_element_courant).donnee)).pid
  312:                 == getpid()) && (pthread_equal((*((struct_thread *)
  313:                 (*l_element_courant).donnee)).tid, pthread_self()) != 0))
  314:         {
  315:             break;
  316:         }
  317: 
  318:         l_element_precedent = l_element_courant;
  319:         l_element_courant = (*l_element_courant).suivant;
  320:     }
  321: 
  322:     if (l_element_courant == NULL)
  323:     {
  324:         pthread_mutex_unlock(&mutex_liste_threads);
  325:         (*s_etat_processus).erreur_systeme = d_es_processus;
  326:         return;
  327:     }
  328: 
  329:     if (l_element_precedent == NULL)
  330:     {
  331:         liste_threads = (*l_element_courant).suivant;
  332:     }
  333:     else
  334:     {
  335:         (*l_element_precedent).suivant = (*l_element_courant).suivant;
  336:     }
  337: 
  338:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  339:     {
  340:         (*s_etat_processus).erreur_systeme = d_es_processus;
  341:         return;
  342:     }
  343: 
  344:     // Le thread ne peut plus traiter de signaux explicites. Il convient
  345:     // alors de corriger le sémaphore pour annuler les signaux en attente.
  346: 
  347:     while((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
  348:             .pointeur_signal_ecriture != (*(*((struct_thread *)
  349:             (*l_element_courant).donnee)).s_etat_processus)
  350:             .pointeur_signal_lecture)
  351:     {
  352:         while(sem_wait(semaphore_signalisation) != 0)
  353:         {
  354:             if (errno != EINTR)
  355:             {
  356:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  357:                 return;
  358:             }
  359:         }
  360: 
  361:         (*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus)
  362:                 .pointeur_signal_lecture = ((*(*((struct_thread *)
  363:                 (*l_element_courant).donnee)).s_etat_processus)
  364:                 .pointeur_signal_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX;
  365:     }
  366: 
  367:     free((void *) (*l_element_courant).donnee);
  368:     free((struct_liste_chainee_volatile *) l_element_courant);
  369: 
  370:     return;
  371: }
  372: 
  373: void
  374: retrait_thread_surveillance(struct_processus *s_etat_processus,
  375:         struct_descripteur_thread *s_argument_thread)
  376: {
  377:     volatile struct_liste_chainee_volatile  *l_element_precedent;
  378:     volatile struct_liste_chainee_volatile  *l_element_courant;
  379: 
  380:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
  381:     {
  382:         (*s_etat_processus).erreur_systeme = d_es_processus;
  383:         return;
  384:     }
  385: 
  386:     l_element_precedent = NULL;
  387:     l_element_courant = liste_threads_surveillance;
  388: 
  389:     while(l_element_courant != NULL)
  390:     {
  391:         if ((*l_element_courant).donnee == (void *) s_argument_thread)
  392:         {
  393:             break;
  394:         }
  395: 
  396:         l_element_precedent = l_element_courant;
  397:         l_element_courant = (*l_element_courant).suivant;
  398:     }
  399: 
  400:     if (l_element_courant == NULL)
  401:     {
  402:         pthread_mutex_unlock(&mutex_liste_threads);
  403:         (*s_etat_processus).erreur_systeme = d_es_processus;
  404:         return;
  405:     }
  406: 
  407:     if (l_element_precedent == NULL)
  408:     {
  409:         liste_threads_surveillance = (*l_element_courant).suivant;
  410:     }
  411:     else
  412:     {
  413:         (*l_element_precedent).suivant = (*l_element_courant).suivant;
  414:     }
  415: 
  416:     if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
  417:             != 0)
  418:     {
  419:         pthread_mutex_unlock(&mutex_liste_threads);
  420:         (*s_etat_processus).erreur_systeme = d_es_processus;
  421:         return;
  422:     }
  423: 
  424:     (*s_argument_thread).nombre_references--;
  425: 
  426:     BUG((*s_argument_thread).nombre_references < 0,
  427:             printf("(*s_argument_thread).nombre_references = %d\n",
  428:             (int) (*s_argument_thread).nombre_references));
  429: 
  430:     if ((*s_argument_thread).nombre_references == 0)
  431:     {
  432:         if (pthread_mutex_unlock(&((*s_argument_thread)
  433:                 .mutex_nombre_references)) != 0)
  434:         {
  435:             pthread_mutex_unlock(&mutex_liste_threads);
  436:             (*s_etat_processus).erreur_systeme = d_es_processus;
  437:             return;
  438:         }
  439: 
  440:         pthread_mutex_destroy(&((*s_argument_thread).mutex));
  441:         pthread_mutex_destroy(&((*s_argument_thread).mutex_nombre_references));
  442:         free(s_argument_thread);
  443:     }
  444:     else
  445:     {
  446:         if (pthread_mutex_unlock(&((*s_argument_thread)
  447:                 .mutex_nombre_references)) != 0)
  448:         {
  449:             pthread_mutex_unlock(&mutex_liste_threads);
  450:             (*s_etat_processus).erreur_systeme = d_es_processus;
  451:             return;
  452:         }
  453:     }
  454: 
  455:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  456:     {
  457:         (*s_etat_processus).erreur_systeme = d_es_processus;
  458:         return;
  459:     }
  460: 
  461:     free((struct_liste_chainee_volatile *) l_element_courant);
  462:     return;
  463: }
  464: 
  465: void
  466: verrouillage_threads_concurrents(struct_processus *s_etat_processus)
  467: {
  468:     volatile struct_liste_chainee_volatile  *l_element_courant;
  469: 
  470:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
  471:     {
  472:         (*s_etat_processus).erreur_systeme = d_es_processus;
  473:         return;
  474:     }
  475: 
  476:     l_element_courant = liste_threads;
  477: 
  478:     while(l_element_courant != NULL)
  479:     {
  480:         if (((*((struct_thread *) (*l_element_courant).donnee)).pid
  481:                 == getpid()) && (pthread_equal((*((struct_thread *)
  482:                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))
  483:         {
  484: #           ifndef SEMAPHORES_NOMMES
  485:                 while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)
  486:                         .donnee)).s_etat_processus).semaphore_fork)) == -1)
  487: #           else
  488:                 while(sem_wait((*(*((struct_thread *) (*l_element_courant)
  489:                         .donnee)).s_etat_processus).semaphore_fork) == -1)
  490: #           endif
  491:             {
  492:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  493:                 return;
  494:             }
  495:         }
  496: 
  497:         l_element_courant = (*l_element_courant).suivant;
  498:     }
  499: 
  500:     return;
  501: }
  502: 
  503: void
  504: deverrouillage_threads_concurrents(struct_processus *s_etat_processus)
  505: {
  506:     volatile struct_liste_chainee_volatile  *l_element_courant;
  507: 
  508:     l_element_courant = liste_threads;
  509: 
  510:     while(l_element_courant != NULL)
  511:     {
  512:         if (((*((struct_thread *) (*l_element_courant).donnee)).pid
  513:                 == getpid()) && (pthread_equal((*((struct_thread *)
  514:                 (*l_element_courant).donnee)).tid, pthread_self()) == 0))
  515:         {
  516: #           ifndef SEMAPHORES_NOMMES
  517:                 if (sem_post(&((*(*((struct_thread *)
  518:                         (*l_element_courant).donnee)).s_etat_processus)
  519:                         .semaphore_fork)) != 0)
  520: #           else
  521:                 if (sem_post((*(*((struct_thread *)
  522:                         (*l_element_courant).donnee)).s_etat_processus)
  523:                         .semaphore_fork) != 0)
  524: #           endif
  525:             {
  526:                 if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  527:                 {
  528:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  529:                     return;
  530:                 }
  531: 
  532:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  533:                 return;
  534:             }
  535:         }
  536: 
  537:         l_element_courant = (*l_element_courant).suivant;
  538:     }
  539: 
  540:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
  541:     {
  542:         (*s_etat_processus).erreur_systeme = d_es_processus;
  543:         return;
  544:     }
  545: 
  546:     return;
  547: }
  548: 
  549: void
  550: liberation_threads(struct_processus *s_etat_processus)
  551: {
  552:     logical1                                    suppression_variables_partagees;
  553: 
  554:     struct_descripteur_thread                   *s_argument_thread;
  555: 
  556:     struct_processus                            *candidat;
  557: 
  558:     struct_liste_variables_partagees            *l_element_partage_courant;
  559:     struct_liste_variables_partagees            *l_element_partage_suivant;
  560: 
  561:     struct_liste_variables_statiques            *l_element_statique_courant;
  562:     struct_liste_variables_statiques            *l_element_statique_suivant;
  563: 
  564:     integer8                                    i;
  565: 
  566:     void                                        *element_candidat;
  567:     void                                        *element_courant;
  568:     void                                        *element_suivant;
  569: 
  570:     volatile struct_liste_chainee_volatile      *l_element_courant;
  571:     volatile struct_liste_chainee_volatile      *l_element_suivant;
  572: 
  573:     if (pthread_mutex_lock(&mutex_liste_threads) == -1)
  574:     {
  575:         (*s_etat_processus).erreur_systeme = d_es_processus;
  576:         return;
  577:     }
  578: 
  579:     l_element_courant = liste_threads;
  580:     suppression_variables_partagees = d_faux;
  581: 
  582:     while(l_element_courant != NULL)
  583:     {
  584:         if ((*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus
  585:                 != s_etat_processus)
  586:         {
  587:             candidat = s_etat_processus;
  588:             s_etat_processus = (*((struct_thread *)
  589:                     (*l_element_courant).donnee)).s_etat_processus;
  590:             free((*s_etat_processus).localisation);
  591: 
  592:             // (*s_etat_processus).instruction_courante peut pointer sur
  593:             // n'importe quoi (une instruction courante ou un champ d'une
  594:             // structure objet). On ne le libère pas quitte à avoir une
  595:             // petite fuite mémoire dans le processus fils.
  596: 
  597:             if ((*s_etat_processus).instruction_courante != NULL)
  598:             {
  599:                 //free((*s_etat_processus).instruction_courante);
  600:             }
  601: 
  602:             close((*s_etat_processus).pipe_acquittement);
  603:             close((*s_etat_processus).pipe_donnees);
  604:             close((*s_etat_processus).pipe_injections);
  605:             close((*s_etat_processus).pipe_nombre_injections);
  606:             close((*s_etat_processus).pipe_interruptions);
  607:             close((*s_etat_processus).pipe_nombre_elements_attente);
  608: 
  609:             liberation(s_etat_processus, (*s_etat_processus).at_exit);
  610: 
  611:             if ((*s_etat_processus).nom_fichier_impression != NULL)
  612:             {
  613:                 free((*s_etat_processus).nom_fichier_impression);
  614:             }
  615: 
  616:             while((*s_etat_processus).fichiers_graphiques != NULL)
  617:             {
  618:                 free((*(*s_etat_processus).fichiers_graphiques).nom);
  619: 
  620:                 if ((*(*s_etat_processus).fichiers_graphiques).legende != NULL)
  621:                 {
  622:                     free((*(*s_etat_processus).fichiers_graphiques).legende);
  623:                 }
  624: 
  625:                 element_courant = (*s_etat_processus).fichiers_graphiques;
  626:                 (*s_etat_processus).fichiers_graphiques =
  627:                         (*(*s_etat_processus).fichiers_graphiques).suivant;
  628: 
  629:                 free(element_courant);
  630:             }
  631: 
  632:             if ((*s_etat_processus).entree_standard != NULL)
  633:             {
  634:                 pclose((*s_etat_processus).entree_standard);
  635:             }
  636: 
  637:             if ((*s_etat_processus).generateur_aleatoire != NULL)
  638:             {
  639:                 liberation_generateur_aleatoire(s_etat_processus);
  640:             }
  641: 
  642:             if ((*s_etat_processus).instruction_derniere_erreur != NULL)
  643:             {
  644:                 free((*s_etat_processus).instruction_derniere_erreur);
  645:                 (*s_etat_processus).instruction_derniere_erreur = NULL;
  646:             }
  647: 
  648:             element_courant = (void *) (*s_etat_processus)
  649:                     .l_base_pile_processus;
  650:             while(element_courant != NULL)
  651:             {
  652:                 s_argument_thread = (struct_descripteur_thread *)
  653:                         (*((struct_liste_chainee *) element_courant)).donnee;
  654: 
  655:                 if (pthread_mutex_lock(&((*s_argument_thread)
  656:                         .mutex_nombre_references)) != 0)
  657:                 {
  658:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  659:                     pthread_mutex_unlock(&mutex_liste_threads);
  660:                     return;
  661:                 }
  662: 
  663:                 (*s_argument_thread).nombre_references--;
  664: 
  665:                 BUG((*s_argument_thread).nombre_references < 0,
  666:                         printf("(*s_argument_thread).nombre_references = %d\n",
  667:                         (int) (*s_argument_thread).nombre_references));
  668: 
  669:                 if ((*s_argument_thread).nombre_references == 0)
  670:                 {
  671:                     close((*s_argument_thread).pipe_objets[0]);
  672:                     close((*s_argument_thread).pipe_acquittement[1]);
  673:                     close((*s_argument_thread).pipe_injections[1]);
  674:                     close((*s_argument_thread).pipe_nombre_injections[1]);
  675:                     close((*s_argument_thread).pipe_nombre_elements_attente[0]);
  676:                     close((*s_argument_thread).pipe_interruptions[0]);
  677: 
  678:                     if (pthread_mutex_unlock(&((*s_argument_thread)
  679:                             .mutex_nombre_references)) != 0)
  680:                     {
  681:                         (*s_etat_processus).erreur_systeme = d_es_processus;
  682:                         pthread_mutex_unlock(&mutex_liste_threads);
  683:                         return;
  684:                     }
  685: 
  686:                     pthread_mutex_destroy(&((*s_argument_thread).mutex));
  687:                     pthread_mutex_destroy(&((*s_argument_thread)
  688:                             .mutex_nombre_references));
  689: 
  690:                     if ((*s_argument_thread).processus_detache == d_faux)
  691:                     {
  692:                         if ((*s_argument_thread).destruction_objet == d_vrai)
  693:                         {
  694:                             liberation(s_etat_processus, (*s_argument_thread)
  695:                                     .argument);
  696:                         }
  697:                     }
  698: 
  699:                     free(s_argument_thread);
  700:                 }
  701:                 else
  702:                 {
  703:                     if (pthread_mutex_unlock(&((*s_argument_thread)
  704:                             .mutex_nombre_references)) != 0)
  705:                     {
  706:                         (*s_etat_processus).erreur_systeme = d_es_processus;
  707:                         pthread_mutex_unlock(&mutex_liste_threads);
  708:                         return;
  709:                     }
  710:                 }
  711: 
  712:                 element_suivant = (*((struct_liste_chainee *) element_courant))
  713:                         .suivant;
  714:                 free(element_courant);
  715:                 element_courant = element_suivant;
  716:             }
  717: 
  718:             (*s_etat_processus).l_base_pile_processus = NULL;
  719: 
  720:             pthread_mutex_trylock(&((*(*s_etat_processus).indep).mutex));
  721:             pthread_mutex_unlock(&((*(*s_etat_processus).indep).mutex));
  722:             liberation(s_etat_processus, (*s_etat_processus).indep);
  723: 
  724:             pthread_mutex_trylock(&((*(*s_etat_processus).depend).mutex));
  725:             pthread_mutex_unlock(&((*(*s_etat_processus).depend).mutex));
  726:             liberation(s_etat_processus, (*s_etat_processus).depend);
  727: 
  728:             free((*s_etat_processus).label_x);
  729:             free((*s_etat_processus).label_y);
  730:             free((*s_etat_processus).label_z);
  731:             free((*s_etat_processus).titre);
  732:             free((*s_etat_processus).legende);
  733: 
  734:             pthread_mutex_trylock(&((*(*s_etat_processus)
  735:                     .parametres_courbes_de_niveau).mutex));
  736:             pthread_mutex_unlock(&((*(*s_etat_processus)
  737:                     .parametres_courbes_de_niveau).mutex));
  738:             liberation(s_etat_processus, (*s_etat_processus)
  739:                     .parametres_courbes_de_niveau);
  740: 
  741:             for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++)
  742:             {
  743:                 if ((*s_etat_processus).corps_interruptions[i] != NULL)
  744:                 {
  745:                     pthread_mutex_trylock(&((*(*s_etat_processus)
  746:                             .corps_interruptions[i]).mutex));
  747:                     pthread_mutex_unlock(&((*(*s_etat_processus)
  748:                             .corps_interruptions[i]).mutex));
  749: 
  750:                     liberation(s_etat_processus,
  751:                             (*s_etat_processus).corps_interruptions[i]);
  752:                 }
  753: 
  754:                 element_courant = (*s_etat_processus)
  755:                         .pile_origine_interruptions[i];
  756: 
  757:                 while(element_courant != NULL)
  758:                 {
  759:                     element_suivant = (*((struct_liste_chainee *)
  760:                             element_courant)).suivant;
  761: 
  762:                     pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
  763:                             element_courant)).donnee).mutex));
  764:                     pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
  765:                             element_courant)).donnee).mutex));
  766: 
  767:                     liberation(s_etat_processus,
  768:                             (*((struct_liste_chainee *) element_courant))
  769:                             .donnee);
  770:                     free(element_courant);
  771: 
  772:                     element_courant = element_suivant;
  773:                 }
  774:             }
  775: 
  776:             // Ne peut être effacé qu'une seule fois
  777:             if (suppression_variables_partagees == d_faux)
  778:             {
  779:                 suppression_variables_partagees = d_vrai;
  780: 
  781:                 liberation_arbre_variables_partagees(s_etat_processus,
  782:                         (*(*s_etat_processus).s_arbre_variables_partagees));
  783:                 (*(*s_etat_processus).s_arbre_variables_partagees) = NULL;
  784: 
  785:                 l_element_partage_courant = (*(*s_etat_processus)
  786:                         .l_liste_variables_partagees);
  787: 
  788:                 while(l_element_partage_courant != NULL)
  789:                 {
  790:                     l_element_partage_suivant =
  791:                             (*l_element_partage_courant).suivant;
  792:                     free(l_element_partage_courant);
  793:                     l_element_partage_courant = l_element_partage_suivant;
  794:                 }
  795: 
  796:                 (*(*s_etat_processus).l_liste_variables_partagees) = NULL;
  797:             }
  798: 
  799:             liberation_arbre_variables(s_etat_processus,
  800:                     (*s_etat_processus).s_arbre_variables, d_faux);
  801: 
  802:             l_element_statique_courant = (*s_etat_processus)
  803:                     .l_liste_variables_statiques;
  804: 
  805:             while(l_element_statique_courant != NULL)
  806:             {
  807:                 l_element_statique_suivant =
  808:                     (*l_element_statique_courant).suivant;
  809:                 free(l_element_statique_courant);
  810:                 l_element_statique_courant = l_element_statique_suivant;
  811:             }
  812: 
  813:             element_courant = (*s_etat_processus).l_base_pile;
  814:             while(element_courant != NULL)
  815:             {
  816:                 element_suivant = (*((struct_liste_chainee *)
  817:                         element_courant)).suivant;
  818: 
  819:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
  820:                         element_courant)).donnee).mutex));
  821:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
  822:                         element_courant)).donnee).mutex));
  823: 
  824:                 liberation(s_etat_processus,
  825:                         (*((struct_liste_chainee *)
  826:                         element_courant)).donnee);
  827:                 free((struct_liste_chainee *) element_courant);
  828: 
  829:                 element_courant = element_suivant;
  830:             }
  831: 
  832:             element_courant = (*s_etat_processus).l_base_pile_contextes;
  833:             while(element_courant != NULL)
  834:             {
  835:                 element_suivant = (*((struct_liste_chainee *)
  836:                         element_courant)).suivant;
  837: 
  838:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
  839:                         element_courant)).donnee).mutex));
  840:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
  841:                         element_courant)).donnee).mutex));
  842:                 liberation(s_etat_processus, (*((struct_liste_chainee *)
  843:                         element_courant)).donnee);
  844:                 free((struct_liste_chainee *) element_courant);
  845: 
  846:                 element_courant = element_suivant;
  847:             }
  848: 
  849:             element_courant = (*s_etat_processus).l_base_pile_taille_contextes;
  850:             while(element_courant != NULL)
  851:             {
  852:                 element_suivant = (*((struct_liste_chainee *)
  853:                         element_courant)).suivant;
  854: 
  855:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
  856:                         element_courant)).donnee).mutex));
  857:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
  858:                         element_courant)).donnee).mutex));
  859:                 liberation(s_etat_processus,
  860:                         (*((struct_liste_chainee *)
  861:                         element_courant)).donnee);
  862:                 free((struct_liste_chainee *) element_courant);
  863: 
  864:                 element_courant = element_suivant;
  865:             }
  866: 
  867:             for(i = 0; i < (*s_etat_processus).nombre_instructions_externes;
  868:                     i++)
  869:             {
  870:                 free((*s_etat_processus).s_instructions_externes[i].nom);
  871:                 free((*s_etat_processus).s_instructions_externes[i]
  872:                         .nom_bibliotheque);
  873:             }
  874: 
  875:             if ((*s_etat_processus).nombre_instructions_externes != 0)
  876:             {
  877:                 free((*s_etat_processus).s_instructions_externes);
  878:             }
  879: 
  880:             element_courant = (*s_etat_processus).s_bibliotheques;
  881:             while(element_courant != NULL)
  882:             {
  883:                 element_suivant = (*((struct_liste_chainee *)
  884:                         element_courant)).suivant;
  885: 
  886:                 element_candidat = (*candidat).s_bibliotheques;
  887:                 while(element_candidat != NULL)
  888:                 {
  889:                     if (((*((struct_bibliotheque *) (*((struct_liste_chainee *)
  890:                             element_courant)).donnee))
  891:                             .descripteur == (*((struct_bibliotheque *)
  892:                             (*((struct_liste_chainee *) element_candidat))
  893:                             .donnee)).descripteur) &&
  894:                             ((*((struct_bibliotheque *)
  895:                             (*((struct_liste_chainee *) element_courant))
  896:                             .donnee)).pid == (*((struct_bibliotheque *)
  897:                             (*((struct_liste_chainee *) element_candidat))
  898:                             .donnee)).pid) && (pthread_equal(
  899:                             (*((struct_bibliotheque *)
  900:                             (*((struct_liste_chainee *) element_courant))
  901:                             .donnee)).tid, (*((struct_bibliotheque *)
  902:                             (*((struct_liste_chainee *) element_candidat))
  903:                             .donnee)).tid) != 0))
  904:                     {
  905:                         break;
  906:                     }
  907: 
  908:                     element_candidat = (*((struct_liste_chainee *)
  909:                             element_candidat)).suivant;
  910:                 }
  911: 
  912:                 if (element_candidat == NULL)
  913:                 {
  914:                     dlclose((*((struct_bibliotheque *)
  915:                             (*((struct_liste_chainee *) element_courant))
  916:                             .donnee)).descripteur);
  917:                 }
  918: 
  919:                 free((*((struct_bibliotheque *)
  920:                         (*((struct_liste_chainee *)
  921:                         element_courant)).donnee)).nom);
  922:                 free((*((struct_liste_chainee *) element_courant)).donnee);
  923:                 free(element_courant);
  924: 
  925:                 element_courant = element_suivant;
  926:             }
  927: 
  928:             element_courant = (*s_etat_processus).l_base_pile_last;
  929:             while(element_courant != NULL)
  930:             {
  931:                 element_suivant = (*((struct_liste_chainee *)
  932:                         element_courant)).suivant;
  933: 
  934:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
  935:                         element_courant)).donnee).mutex));
  936:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
  937:                         element_courant)).donnee).mutex));
  938:                 liberation(s_etat_processus,
  939:                         (*((struct_liste_chainee *) element_courant)).donnee);
  940:                 free(element_courant);
  941: 
  942:                 element_courant = element_suivant;
  943:             }
  944: 
  945:             element_courant = (*s_etat_processus).l_base_pile_systeme;
  946:             while(element_courant != NULL)
  947:             {
  948:                 element_suivant = (*((struct_liste_pile_systeme *)
  949:                         element_courant)).suivant;
  950: 
  951:                 if ((*((struct_liste_pile_systeme *)
  952:                         element_courant)).indice_boucle != NULL)
  953:                 {
  954:                     pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
  955:                             element_courant)).indice_boucle).mutex));
  956:                     pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
  957:                             element_courant)).indice_boucle).mutex));
  958:                 }
  959: 
  960:                 liberation(s_etat_processus,
  961:                         (*((struct_liste_pile_systeme *)
  962:                         element_courant)).indice_boucle);
  963: 
  964:                 if ((*((struct_liste_pile_systeme *)
  965:                         element_courant)).limite_indice_boucle != NULL)
  966:                 {
  967:                     pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
  968:                             element_courant)).limite_indice_boucle).mutex));
  969:                     pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
  970:                             element_courant)).limite_indice_boucle).mutex));
  971:                 }
  972: 
  973:                 liberation(s_etat_processus,
  974:                         (*((struct_liste_pile_systeme *)
  975:                         element_courant)).limite_indice_boucle);
  976: 
  977:                 if ((*((struct_liste_pile_systeme *)
  978:                         element_courant)).objet_de_test != NULL)
  979:                 {
  980:                     pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
  981:                             element_courant)).objet_de_test).mutex));
  982:                     pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
  983:                             element_courant)).objet_de_test).mutex));
  984:                 }
  985: 
  986:                 liberation(s_etat_processus,
  987:                         (*((struct_liste_pile_systeme *)
  988:                         element_courant)).objet_de_test);
  989: 
  990:                 if ((*((struct_liste_pile_systeme *)
  991:                         element_courant)).nom_variable != NULL)
  992:                 {
  993:                     free((*((struct_liste_pile_systeme *)
  994:                             element_courant)).nom_variable);
  995:                 }
  996: 
  997:                 free(element_courant);
  998: 
  999:                 element_courant = element_suivant;
 1000:             }
 1001: 
 1002:             element_courant = (*s_etat_processus).s_fichiers;
 1003:             while(element_courant != NULL)
 1004:             {
 1005:                 element_suivant = (*((struct_liste_chainee *)
 1006:                         element_courant)).suivant;
 1007: 
 1008:                 element_candidat = (*candidat).s_fichiers;
 1009:                 while(element_candidat != NULL)
 1010:                 {
 1011:                     if (((*((struct_descripteur_fichier *)
 1012:                             (*((struct_liste_chainee *) element_courant))
 1013:                             .donnee)).pid ==
 1014:                             (*((struct_descripteur_fichier *)
 1015:                             (*((struct_liste_chainee *) element_candidat))
 1016:                             .donnee)).pid) && (pthread_equal(
 1017:                             (*((struct_descripteur_fichier *)
 1018:                             (*((struct_liste_chainee *) element_courant))
 1019:                             .donnee)).tid, (*((struct_descripteur_fichier *)
 1020:                             (*((struct_liste_chainee *) element_candidat))
 1021:                             .donnee)).tid) != 0))
 1022:                     {
 1023:                         if ((*((struct_descripteur_fichier *)
 1024:                                 (*((struct_liste_chainee *) element_courant))
 1025:                                 .donnee)).type ==
 1026:                                 (*((struct_descripteur_fichier *)
 1027:                                 (*((struct_liste_chainee *) element_candidat))
 1028:                                 .donnee)).type)
 1029:                         {
 1030:                             if ((*((struct_descripteur_fichier *)
 1031:                                     (*((struct_liste_chainee *)
 1032:                                     element_candidat)).donnee)).type == 'C')
 1033:                             {
 1034:                                 if ((*((struct_descripteur_fichier *)
 1035:                                         (*((struct_liste_chainee *)
 1036:                                         element_courant)).donnee))
 1037:                                         .descripteur_c ==
 1038:                                         (*((struct_descripteur_fichier *)
 1039:                                         (*((struct_liste_chainee *)
 1040:                                         element_candidat)).donnee))
 1041:                                         .descripteur_c)
 1042:                                 {
 1043:                                     break;
 1044:                                 }
 1045:                             }
 1046:                             else
 1047:                             {
 1048:                                 if (((*((struct_descripteur_fichier *)
 1049:                                         (*((struct_liste_chainee *)
 1050:                                         element_courant)).donnee))
 1051:                                         .descripteur_sqlite ==
 1052:                                         (*((struct_descripteur_fichier *)
 1053:                                         (*((struct_liste_chainee *)
 1054:                                         element_candidat)).donnee))
 1055:                                         .descripteur_sqlite) &&
 1056:                                         ((*((struct_descripteur_fichier *)
 1057:                                         (*((struct_liste_chainee *)
 1058:                                         element_courant)).donnee))
 1059:                                         .descripteur_c ==
 1060:                                         (*((struct_descripteur_fichier *)
 1061:                                         (*((struct_liste_chainee *)
 1062:                                         element_candidat)).donnee))
 1063:                                         .descripteur_c))
 1064:                                 {
 1065:                                     break;
 1066:                                 }
 1067:                             }
 1068:                         }
 1069:                     }
 1070: 
 1071:                     element_candidat = (*((struct_liste_chainee *)
 1072:                             element_candidat)).suivant;
 1073:                 }
 1074: 
 1075:                 if (element_candidat == NULL)
 1076:                 {
 1077:                     fclose((*((struct_descripteur_fichier *)
 1078:                             (*((struct_liste_chainee *) element_courant))
 1079:                             .donnee)).descripteur_c);
 1080: 
 1081:                     if ((*((struct_descripteur_fichier *)
 1082:                             (*((struct_liste_chainee *) element_courant))
 1083:                             .donnee)).type != 'C')
 1084:                     {
 1085:                         sqlite3_close((*((struct_descripteur_fichier *)
 1086:                                 (*((struct_liste_chainee *) element_courant))
 1087:                                 .donnee)).descripteur_sqlite);
 1088:                     }
 1089:                 }
 1090: 
 1091:                 free((*((struct_descripteur_fichier *)
 1092:                         (*((struct_liste_chainee *)
 1093:                         element_courant)).donnee)).nom);
 1094:                 free((struct_descripteur_fichier *)
 1095:                         (*((struct_liste_chainee *)
 1096:                         element_courant)).donnee);
 1097:                 free(element_courant);
 1098: 
 1099:                 element_courant = element_suivant;
 1100:             }
 1101: 
 1102:             element_courant = (*s_etat_processus).s_sockets;
 1103:             while(element_courant != NULL)
 1104:             {
 1105:                 element_suivant = (*((struct_liste_chainee *)
 1106:                         element_courant)).suivant;
 1107: 
 1108:                 element_candidat = (*candidat).s_sockets;
 1109:                 while(element_candidat != NULL)
 1110:                 {
 1111:                     if (((*((struct_socket *)
 1112:                             (*((struct_liste_chainee *) element_courant))
 1113:                             .donnee)).socket == (*((struct_socket *)
 1114:                             (*((struct_liste_chainee *) element_candidat))
 1115:                             .donnee)).socket) &&
 1116:                             ((*((struct_socket *)
 1117:                             (*((struct_liste_chainee *) element_courant))
 1118:                             .donnee)).pid == (*((struct_socket *)
 1119:                             (*((struct_liste_chainee *) element_candidat))
 1120:                             .donnee)).pid) && (pthread_equal(
 1121:                             (*((struct_socket *)
 1122:                             (*((struct_liste_chainee *) element_courant))
 1123:                             .donnee)).tid, (*((struct_socket *)
 1124:                             (*((struct_liste_chainee *) element_candidat))
 1125:                             .donnee)).tid) != 0))
 1126:                     {
 1127:                         break;
 1128:                     }
 1129: 
 1130:                     element_candidat = (*((struct_liste_chainee *)
 1131:                             element_candidat)).suivant;
 1132:                 }
 1133: 
 1134:                 if (element_candidat == NULL)
 1135:                 {
 1136:                     if ((*((struct_socket *) (*((struct_liste_chainee *)
 1137:                             element_courant)).donnee)).socket_connectee
 1138:                             == d_vrai)
 1139:                     {
 1140:                         shutdown((*((struct_socket *)
 1141:                                 (*((struct_liste_chainee *) element_courant))
 1142:                                 .donnee)).socket, SHUT_RDWR);
 1143:                     }
 1144: 
 1145:                     close((*((struct_socket *)
 1146:                             (*((struct_liste_chainee *) element_courant))
 1147:                             .donnee)).socket);
 1148:                 }
 1149: 
 1150:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
 1151:                         element_courant)).donnee).mutex));
 1152:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
 1153:                         element_courant)).donnee).mutex));
 1154: 
 1155:                 liberation(s_etat_processus,
 1156:                         (*((struct_liste_chainee *)
 1157:                         element_courant)).donnee);
 1158:                 free(element_courant);
 1159: 
 1160:                 element_courant = element_suivant;
 1161:             }
 1162: 
 1163: /*
 1164: ================================================================================
 1165:   À noter : on ne ferme pas la connexion car la conséquence immédiate est
 1166:   une destruction de l'objet pour le processus père.
 1167: ================================================================================
 1168: 
 1169:             element_courant = (*s_etat_processus).s_connecteurs_sql;
 1170:             while(element_courant != NULL)
 1171:             {
 1172:                 element_suivant = (*((struct_liste_chainee *)
 1173:                         element_courant)).suivant;
 1174: 
 1175:                 element_candidat = (*candidat).s_connecteurs_sql;
 1176:                 while(element_candidat != NULL)
 1177:                 {
 1178:                     if (((
 1179: #ifdef MYSQL_SUPPORT
 1180:                             ((*((struct_connecteur_sql *)
 1181:                             (*((struct_liste_chainee *) element_courant))
 1182:                             .donnee)).descripteur.mysql ==
 1183:                             (*((struct_connecteur_sql *)
 1184:                             (*((struct_liste_chainee *) element_candidat))
 1185:                             .donnee)).descripteur.mysql)
 1186:                             &&
 1187:                             (strcmp((*((struct_connecteur_sql *)
 1188:                             (*((struct_liste_chainee *) element_courant))
 1189:                             .donnee)).type, "MYSQL") == 0)
 1190:                             &&
 1191:                             (strcmp((*((struct_connecteur_sql *)
 1192:                             (*((struct_liste_chainee *) element_candidat))
 1193:                             .donnee)).type, "MYSQL") == 0)
 1194: #else
 1195:                             0
 1196: #endif
 1197:                             ) || (
 1198: #ifdef POSTGRESQL_SUPPORT
 1199:                             ((*((struct_connecteur_sql *)
 1200:                             (*((struct_liste_chainee *) element_courant))
 1201:                             .donnee)).descripteur.postgresql ==
 1202:                             (*((struct_connecteur_sql *)
 1203:                             (*((struct_liste_chainee *) element_candidat))
 1204:                             .donnee)).descripteur.postgresql)
 1205:                             &&
 1206:                             (strcmp((*((struct_connecteur_sql *)
 1207:                             (*((struct_liste_chainee *) element_courant))
 1208:                             .donnee)).type, "POSTGRESQL") == 0)
 1209:                             &&
 1210:                             (strcmp((*((struct_connecteur_sql *)
 1211:                             (*((struct_liste_chainee *) element_candidat))
 1212:                             .donnee)).type, "POSTGRESQL") == 0)
 1213: #else
 1214:                             0
 1215: #endif
 1216:                             )) &&
 1217:                             ((*((struct_connecteur_sql *)
 1218:                             (*((struct_liste_chainee *) element_courant))
 1219:                             .donnee)).pid == (*((struct_connecteur_sql *)
 1220:                             (*((struct_liste_chainee *) element_candidat))
 1221:                             .donnee)).pid) && (pthread_equal(
 1222:                             (*((struct_connecteur_sql *)
 1223:                             (*((struct_liste_chainee *) element_courant))
 1224:                             .donnee)).tid, (*((struct_connecteur_sql *)
 1225:                             (*((struct_liste_chainee *) element_candidat))
 1226:                             .donnee)).tid) != 0))
 1227:                     {
 1228:                         break;
 1229:                     }
 1230: 
 1231:                     element_candidat = (*((struct_liste_chainee *)
 1232:                             element_candidat)).suivant;
 1233:                 }
 1234: 
 1235:                 if (element_candidat == NULL)
 1236:                 {
 1237:                     sqlclose((*((struct_liste_chainee *) element_courant))
 1238:                             .donnee);
 1239:                 }
 1240: 
 1241:                 pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
 1242:                         element_courant)).donnee).mutex));
 1243:                 pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
 1244:                         element_courant)).donnee).mutex));
 1245: 
 1246:                 liberation(s_etat_processus, (*((struct_liste_chainee *)
 1247:                         element_courant)).donnee);
 1248:                 free(element_courant);
 1249: 
 1250:                 element_courant = element_suivant;
 1251:             }
 1252: */
 1253: 
 1254:             (*s_etat_processus).s_connecteurs_sql = NULL;
 1255: 
 1256:             element_courant = (*s_etat_processus).s_marques;
 1257:             while(element_courant != NULL)
 1258:             {
 1259:                 free((*((struct_marque *) element_courant)).label);
 1260:                 free((*((struct_marque *) element_courant)).position);
 1261:                 element_suivant = (*((struct_marque *) element_courant))
 1262:                         .suivant;
 1263:                 free(element_courant);
 1264:                 element_courant = element_suivant;
 1265:             }
 1266: 
 1267:             liberation_allocateur(s_etat_processus);
 1268: 
 1269: #           ifndef SEMAPHORES_NOMMES
 1270:                 sem_post(&((*s_etat_processus).semaphore_fork));
 1271:                 sem_destroy(&((*s_etat_processus).semaphore_fork));
 1272: #           else
 1273:                 sem_post((*s_etat_processus).semaphore_fork);
 1274:                 sem_close((*s_etat_processus).semaphore_fork);
 1275: #           endif
 1276: 
 1277:             liberation_contexte_cas(s_etat_processus);
 1278:             liberation_allocateur_buffer(s_etat_processus);
 1279:             sys_free(s_etat_processus);
 1280: 
 1281:             s_etat_processus = candidat;
 1282:         }
 1283: 
 1284:         l_element_suivant = (*l_element_courant).suivant;
 1285: 
 1286:         free((struct_thread *) (*l_element_courant).donnee);
 1287:         free((struct_liste_chainee *) l_element_courant);
 1288: 
 1289:         l_element_courant = l_element_suivant;
 1290:     }
 1291: 
 1292:     liste_threads = NULL;
 1293: 
 1294:     l_element_courant = liste_threads_surveillance;
 1295: 
 1296:     while(l_element_courant != NULL)
 1297:     {
 1298:         s_argument_thread = (struct_descripteur_thread *)
 1299:                 (*l_element_courant).donnee;
 1300: 
 1301:         if (pthread_mutex_lock(&((*s_argument_thread).mutex_nombre_references))
 1302:                 != 0)
 1303:         {
 1304:             (*s_etat_processus).erreur_systeme = d_es_processus;
 1305:             pthread_mutex_unlock(&mutex_liste_threads);
 1306:             return;
 1307:         }
 1308: 
 1309:         (*s_argument_thread).nombre_references--;
 1310: 
 1311:         BUG((*s_argument_thread).nombre_references < 0,
 1312:                 printf("(*s_argument_thread).nombre_references = %d\n",
 1313:                 (int) (*s_argument_thread).nombre_references));
 1314: 
 1315:         if ((*s_argument_thread).nombre_references == 0)
 1316:         {
 1317:             close((*s_argument_thread).pipe_objets[0]);
 1318:             close((*s_argument_thread).pipe_acquittement[1]);
 1319:             close((*s_argument_thread).pipe_injections[1]);
 1320:             close((*s_argument_thread).pipe_nombre_injections[1]);
 1321:             close((*s_argument_thread).pipe_nombre_elements_attente[0]);
 1322:             close((*s_argument_thread).pipe_interruptions[0]);
 1323: 
 1324:             if (pthread_mutex_unlock(&((*s_argument_thread)
 1325:                     .mutex_nombre_references)) != 0)
 1326:             {
 1327:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 1328:                 pthread_mutex_unlock(&mutex_liste_threads);
 1329:                 return;
 1330:             }
 1331: 
 1332:             pthread_mutex_destroy(&((*s_argument_thread).mutex));
 1333:             pthread_mutex_destroy(&((*s_argument_thread)
 1334:                     .mutex_nombre_references));
 1335: 
 1336:             if ((*s_argument_thread).processus_detache == d_faux)
 1337:             {
 1338:                 if ((*s_argument_thread).destruction_objet == d_vrai)
 1339:                 {
 1340:                     liberation(s_etat_processus, (*s_argument_thread).argument);
 1341:                 }
 1342:             }
 1343: 
 1344:             free(s_argument_thread);
 1345:         }
 1346:         else
 1347:         {
 1348:             if (pthread_mutex_unlock(&((*s_argument_thread)
 1349:                     .mutex_nombre_references)) != 0)
 1350:             {
 1351:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 1352:                 pthread_mutex_unlock(&mutex_liste_threads);
 1353:                 return;
 1354:             }
 1355:         }
 1356: 
 1357:         l_element_suivant = (*l_element_courant).suivant;
 1358:         free((struct_liste_chainee *) l_element_courant);
 1359:         l_element_courant = l_element_suivant;
 1360:     }
 1361: 
 1362:     liste_threads_surveillance = NULL;
 1363: 
 1364:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
 1365:     {
 1366:         (*s_etat_processus).erreur_systeme = d_es_processus;
 1367:         return;
 1368:     }
 1369: 
 1370:     return;
 1371: }
 1372: 
 1373: static struct_processus *
 1374: recherche_thread(pid_t pid, pthread_t tid)
 1375: {
 1376:     volatile struct_liste_chainee_volatile      *l_element_courant;
 1377: 
 1378:     struct_processus                            *s_etat_processus;
 1379: 
 1380:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
 1381:     {
 1382:         return(NULL);
 1383:     }
 1384: 
 1385:     l_element_courant = liste_threads;
 1386: 
 1387:     while(l_element_courant != NULL)
 1388:     {
 1389:         if ((pthread_equal((*((struct_thread *) (*l_element_courant).donnee))
 1390:                 .tid, tid) != 0) && ((*((struct_thread *)
 1391:                 (*l_element_courant).donnee)).pid == pid))
 1392:         {
 1393:             break;
 1394:         }
 1395: 
 1396:         l_element_courant = (*l_element_courant).suivant;
 1397:     }
 1398: 
 1399:     if (l_element_courant == NULL)
 1400:     {
 1401:         /*
 1402:          * Le processus n'existe plus. On ne distribue aucun signal.
 1403:          */
 1404: 
 1405:         pthread_mutex_unlock(&mutex_liste_threads);
 1406:         return(NULL);
 1407:     }
 1408: 
 1409:     s_etat_processus = (*((struct_thread *)
 1410:             (*l_element_courant).donnee)).s_etat_processus;
 1411: 
 1412:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
 1413:     {
 1414:         return(NULL);
 1415:     }
 1416: 
 1417:     return(s_etat_processus);
 1418: }
 1419: 
 1420: static struct_processus *
 1421: recherche_thread_principal(pid_t pid)
 1422: {
 1423:     volatile struct_liste_chainee_volatile      *l_element_courant;
 1424: 
 1425:     l_element_courant = liste_threads;
 1426: 
 1427:     while(l_element_courant != NULL)
 1428:     {
 1429:         if (((*((struct_thread *) (*l_element_courant).donnee)).thread_principal
 1430:                 == d_vrai) && ((*((struct_thread *)
 1431:                 (*l_element_courant).donnee)).pid == pid))
 1432:         {
 1433:             break;
 1434:         }
 1435: 
 1436:         l_element_courant = (*l_element_courant).suivant;
 1437:     }
 1438: 
 1439:     if (l_element_courant == NULL)
 1440:     {
 1441:         /*
 1442:          * Le processus n'existe plus. On ne distribue aucun signal.
 1443:          */
 1444: 
 1445:         return(NULL);
 1446:     }
 1447: 
 1448:     return((*((struct_thread *) (*l_element_courant).donnee))
 1449:             .s_etat_processus);
 1450: }
 1451: 
 1452: 
 1453: /*
 1454: ================================================================================
 1455:   Procédures de gestion des signaux d'interruption
 1456: ================================================================================
 1457:   Entrée : variable globale
 1458: --------------------------------------------------------------------------------
 1459:   Sortie : variable globale modifiée
 1460: --------------------------------------------------------------------------------
 1461:   Effets de bord : néant
 1462: ================================================================================
 1463: */
 1464: 
 1465: // Les routines suivantes sont uniquement appelées depuis les gestionnaires
 1466: // des signaux asynchrones. Elles ne doivent pas bloquer dans le cas où
 1467: // les sémaphores sont déjà bloqués par un gestionnaire de signal.
 1468: 
 1469: static inline void
 1470: verrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 1471: {
 1472: #   ifndef SEMAPHORES_NOMMES
 1473:     if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
 1474: #   else
 1475:     if (sem_post((*s_etat_processus).semaphore_fork) != 0)
 1476: #   endif
 1477:     {
 1478:         BUG(1, uprintf("Lock error !\n"));
 1479:         return;
 1480:     }
 1481: 
 1482:     return;
 1483: }
 1484: 
 1485: static inline void
 1486: deverrouillage_gestionnaire_signaux(struct_processus *s_etat_processus)
 1487: {
 1488: #   ifndef SEMAPHORES_NOMMES
 1489:     while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
 1490: #   else
 1491:     while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
 1492: #   endif
 1493:     {
 1494:         if (errno != EINTR)
 1495:         {
 1496:             BUG(1, uprintf("Unlock error !\n"));
 1497:             return;
 1498:         }
 1499:     }
 1500: 
 1501:     return;
 1502: }
 1503: 
 1504: /*
 1505: ================================================================================
 1506:   Fonctions de gestion des signaux dans les threads.
 1507: 
 1508:   Lorsqu'un processus reçoit un signal, il appelle le gestionnaire de signal
 1509:   associé qui ne fait qu'envoyer au travers de write() le signal
 1510:   reçus dans un pipe. Un second thread est bloqué sur ce pipe et
 1511:   effectue le traitement adéquat pour le signal donné.
 1512: ================================================================================
 1513: */
 1514: 
 1515: #define test_signal(signal) \
 1516:     if (signal_test == SIGTEST) { signal_test = signal; return; }
 1517: 
 1518: static int          pipe_signaux;
 1519: 
 1520: logical1
 1521: lancement_thread_signaux(struct_processus *s_etat_processus)
 1522: {
 1523:     pthread_attr_t                  attributs;
 1524: 
 1525:     if (pipe((*s_etat_processus).pipe_signaux) != 0)
 1526:     {
 1527:         (*s_etat_processus).erreur_systeme = d_es_processus;
 1528:         return(d_erreur);
 1529:     }
 1530: 
 1531:     pipe_signaux = (*s_etat_processus).pipe_signaux[1];
 1532: 
 1533:     if (pthread_attr_init(&attributs) != 0)
 1534:     {
 1535:         (*s_etat_processus).erreur_systeme = d_es_processus;
 1536:         return(d_erreur);
 1537:     }
 1538: 
 1539:     if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
 1540:     {
 1541:         (*s_etat_processus).erreur_systeme = d_es_processus;
 1542:         return(d_erreur);
 1543:     }
 1544: 
 1545:     if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
 1546:             thread_signaux, s_etat_processus) != 0)
 1547:     {
 1548:         (*s_etat_processus).erreur_systeme = d_es_processus;
 1549:         return(d_erreur);
 1550:     }
 1551: 
 1552:     return(d_absence_erreur);
 1553: }
 1554: 
 1555: logical1
 1556: arret_thread_signaux(struct_processus *s_etat_processus)
 1557: {
 1558:     unsigned char       signal;
 1559:     ssize_t             n;
 1560: 
 1561:     signal = (unsigned char ) (rpl_sigmax & 0xFF);
 1562: 
 1563:     do
 1564:     {
 1565:         n = write_atomic(s_etat_processus, (*s_etat_processus).pipe_signaux[1],
 1566:                 &signal, sizeof(signal));
 1567: 
 1568:         if (n < 0)
 1569:         {
 1570:             return(d_erreur);
 1571:         }
 1572:     } while(n != 1);
 1573: 
 1574:     pthread_join((*s_etat_processus).thread_signaux, NULL);
 1575: 
 1576:     close((*s_etat_processus).pipe_signaux[0]);
 1577:     close((*s_etat_processus).pipe_signaux[1]);
 1578: 
 1579:     return(d_absence_erreur);
 1580: }
 1581: 
 1582: void *
 1583: thread_signaux(void *argument)
 1584: {
 1585:     int                     *pipe;
 1586: 
 1587:     sigset_t                masque;
 1588: 
 1589:     struct pollfd           fds;
 1590: 
 1591:     struct_processus        *s_etat_processus;
 1592: 
 1593:     unsigned char           signal;
 1594: 
 1595:     s_etat_processus = (struct_processus *) argument;
 1596:     pipe = (*s_etat_processus).pipe_signaux;
 1597:     fds.fd = pipe[0];
 1598:     fds.events = POLLIN;
 1599:     fds.revents = 0;
 1600: 
 1601:     sigfillset(&masque);
 1602:     pthread_sigmask(SIG_BLOCK, &masque, NULL);
 1603: 
 1604:     do
 1605:     {
 1606:         if (poll(&fds, 1, -1) == -1)
 1607:         {
 1608:             pthread_exit(NULL);
 1609:         }
 1610: 
 1611:         if (read_atomic(s_etat_processus, fds.fd, &signal, 1) != 1)
 1612:         {
 1613:             pthread_exit(NULL);
 1614:         }
 1615: 
 1616:         if (signal != (0xFF & rpl_sigmax))
 1617:         {
 1618:             envoi_signal_processus(getpid(), signal, d_faux);
 1619:             // Un signal SIGALRM est envoyé par le thread de surveillance
 1620:             // des signaux jusqu'à ce que les signaux soient tous traités.
 1621:         }
 1622:     } while(signal != (0xFF & rpl_sigmax));
 1623: 
 1624:     pthread_exit(NULL);
 1625: }
 1626: 
 1627: 
 1628: static inline void
 1629: _write(int fd, const void *buf, size_t count)
 1630: {
 1631:     ssize_t         ios;
 1632: 
 1633:     while((ios = write(fd, buf, count)) == -1)
 1634:     {
 1635:         if (errno != EINTR)
 1636:         {
 1637:             break;
 1638:         }
 1639:     }
 1640: 
 1641:     return;
 1642: }
 1643: 
 1644: 
 1645: // Récupération des signaux
 1646: // - SIGINT  (arrêt au clavier)
 1647: // - SIGTERM (signal d'arrêt en provenance du système)
 1648: 
 1649: void
 1650: interruption1(int signal)
 1651: {
 1652:     unsigned char       signal_tronque;
 1653: 
 1654:     test_signal(signal);
 1655: 
 1656:     switch(signal)
 1657:     {
 1658:         case SIGINT:
 1659:             signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
 1660:             _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1661:             break;
 1662: 
 1663:         case SIGTERM:
 1664:             signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
 1665:             _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1666:             break;
 1667: 
 1668:         case SIGUSR1:
 1669:             signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
 1670:             _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1671:             break;
 1672: 
 1673:         default:
 1674:             // SIGALRM
 1675:             break;
 1676:     }
 1677: 
 1678:     return;
 1679: }
 1680: 
 1681: // Récupération des signaux
 1682: // - SIGFSTP
 1683: //
 1684: // ATTENTION :
 1685: // Le signal SIGFSTP provient de la mort du processus de contrôle.
 1686: // Sous certains systèmes (Linux...), la mort du terminal de contrôle
 1687: // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
 1688: // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
 1689: // non initialisée (pointeur NULL) issue de TERMIO.
 1690: 
 1691: void
 1692: interruption2(int signal)
 1693: {
 1694:     unsigned char       signal_tronque;
 1695: 
 1696:     test_signal(signal);
 1697: 
 1698:     signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
 1699:     _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1700: 
 1701:     return;
 1702: }
 1703: 
 1704: void
 1705: interruption3(int signal)
 1706: {
 1707:     // Si on passe par ici, c'est qu'il est impossible de récupérer
 1708:     // l'erreur d'accès à la mémoire. On sort donc du programme quitte à
 1709:     // ce qu'il reste des processus orphelins.
 1710: 
 1711:     unsigned char       message_1[] = "+++System : Uncaught access violation\n"
 1712:                                 "+++System : Aborting !\n";
 1713:     unsigned char       message_2[] = "+++System : Stack overflow\n"
 1714:                                 "+++System : Aborting !\n";
 1715: 
 1716:     test_signal(signal);
 1717: 
 1718:     if (pid_processus_pere == getpid())
 1719:     {
 1720:         kill(pid_processus_pere, SIGUSR1);
 1721:     }
 1722: 
 1723: #   pragma GCC diagnostic push
 1724: #   pragma GCC diagnostic ignored "-Wunused-result"
 1725: 
 1726:     if (signal != SIGUSR2)
 1727:     {
 1728:         write(STDERR_FILENO, message_1, strlen(message_1));
 1729:     }
 1730:     else
 1731:     {
 1732:         write(STDERR_FILENO, message_2, strlen(message_2));
 1733:     }
 1734: 
 1735: #   pragma GCC diagnostic pop
 1736: 
 1737:     _exit(EXIT_FAILURE);
 1738: }
 1739: 
 1740: // Récupération des signaux
 1741: // - SIGHUP
 1742: 
 1743: void
 1744: interruption4(int signal)
 1745: {
 1746:     unsigned char       signal_tronque;
 1747: 
 1748:     test_signal(signal);
 1749: 
 1750:     signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
 1751:     _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1752: 
 1753:     return;
 1754: }
 1755: 
 1756: // Récupération des signaux
 1757: // - SIGPIPE
 1758: 
 1759: void
 1760: interruption5(int signal)
 1761: {
 1762:     unsigned char       message[] = "+++System : SIGPIPE\n"
 1763:                                 "+++System : Aborting !\n";
 1764:     unsigned char       signal_tronque;
 1765: 
 1766:     test_signal(signal);
 1767: 
 1768: #   pragma GCC diagnostic push
 1769: #   pragma GCC diagnostic ignored "-Wunused-result"
 1770: 
 1771:     if (pid_processus_pere == getpid())
 1772:     {
 1773:         signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
 1774:         _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
 1775:     }
 1776: 
 1777:     write(STDERR_FILENO, message, strlen(message));
 1778: 
 1779: #   pragma GCC diagnostic pop
 1780: 
 1781:     return;
 1782: }
 1783: 
 1784: inline static void
 1785: signal_alrm(struct_processus *s_etat_processus, pid_t pid)
 1786: {
 1787:     struct_processus        *s_thread_principal;
 1788: 
 1789:     verrouillage_gestionnaire_signaux(s_etat_processus);
 1790: 
 1791:     if (pid == getpid())
 1792:     {
 1793:         // Si pid est égal à getpid(), le signal à traiter est issu
 1794:         // du même processus que celui qui va le traiter, mais d'un thread
 1795:         // différent.
 1796: 
 1797:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 1798:         {
 1799:             printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
 1800:                     (unsigned long long) pthread_self());
 1801:             fflush(stdout);
 1802:         }
 1803: 
 1804:         if ((*s_etat_processus).pid_processus_pere != getpid())
 1805:         {
 1806:             // On n'est pas dans le processus père, on remonte le signal.
 1807:             envoi_signal_processus((*s_etat_processus).pid_processus_pere,
 1808:                     rpl_sigalrm, d_faux);
 1809:         }
 1810:         else
 1811:         {
 1812:             // On est dans le processus père, on effectue un arrêt d'urgence.
 1813:             (*s_etat_processus).var_volatile_alarme = -1;
 1814:             (*s_etat_processus).var_volatile_requete_arret = -1;
 1815:         }
 1816:     }
 1817:     else
 1818:     {
 1819:         // Le signal est issu d'un processus différent. On recherche le
 1820:         // thread principal pour remonter le signal.
 1821: 
 1822:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 1823:                 != NULL)
 1824:         {
 1825:             envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
 1826:         }
 1827:     }
 1828: 
 1829:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 1830:     return;
 1831: }
 1832: 
 1833: inline static void
 1834: signal_term(struct_processus *s_etat_processus, pid_t pid)
 1835: {
 1836:     struct_processus        *s_thread_principal;
 1837:     pthread_mutex_t         exclusion = PTHREAD_MUTEX_INITIALIZER;
 1838: 
 1839:     verrouillage_gestionnaire_signaux(s_etat_processus);
 1840: 
 1841:     if (pid == getpid())
 1842:     {
 1843:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 1844:         {
 1845:             printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
 1846:                     (unsigned long long) pthread_self());
 1847:             fflush(stdout);
 1848:         }
 1849: 
 1850:         if ((*s_etat_processus).pid_processus_pere != getpid())
 1851:         {
 1852:             envoi_signal_processus((*s_etat_processus).pid_processus_pere,
 1853:                     rpl_sigterm, d_faux);
 1854:         }
 1855:         else
 1856:         {
 1857:             (*s_etat_processus).var_volatile_traitement_sigint = -1;
 1858: 
 1859:             pthread_mutex_lock(&exclusion);
 1860: 
 1861:             if ((*s_etat_processus).var_volatile_requete_arret == -1)
 1862:             {
 1863:                 deverrouillage_gestionnaire_signaux(s_etat_processus);
 1864:                 pthread_mutex_unlock(&exclusion);
 1865:                 return;
 1866:             }
 1867: 
 1868:             (*s_etat_processus).var_volatile_requete_arret = -1;
 1869:             (*s_etat_processus).var_volatile_alarme = -1;
 1870: 
 1871:             pthread_mutex_unlock(&exclusion);
 1872:         }
 1873:     }
 1874:     else
 1875:     {
 1876:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 1877:                 != NULL)
 1878:         {
 1879:             envoi_signal_contexte(s_thread_principal, rpl_sigterm);
 1880:         }
 1881:     }
 1882: 
 1883:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 1884:     return;
 1885: }
 1886: 
 1887: inline static void
 1888: signal_int(struct_processus *s_etat_processus, pid_t pid)
 1889: {
 1890:     struct_processus        *s_thread_principal;
 1891:     volatile sig_atomic_t   exclusion = 0;
 1892: 
 1893:     verrouillage_gestionnaire_signaux(s_etat_processus);
 1894: 
 1895:     if (pid == getpid())
 1896:     {
 1897:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 1898:         {
 1899:             printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
 1900:                     (unsigned long long) pthread_self());
 1901:             fflush(stdout);
 1902:         }
 1903: 
 1904:         if ((*s_etat_processus).pid_processus_pere != getpid())
 1905:         {
 1906:             envoi_signal_processus((*s_etat_processus).pid_processus_pere,
 1907:                     rpl_sigint, d_faux);
 1908:         }
 1909:         else
 1910:         {
 1911:             (*s_etat_processus).var_volatile_traitement_sigint = -1;
 1912: 
 1913:             while(exclusion == 1);
 1914:             exclusion = 1;
 1915: 
 1916:             if ((*s_etat_processus).var_volatile_requete_arret == -1)
 1917:             {
 1918:                 deverrouillage_gestionnaire_signaux(s_etat_processus);
 1919:                 exclusion = 0;
 1920:                 return;
 1921:             }
 1922: 
 1923:             if ((*s_etat_processus).langue == 'F')
 1924:             {
 1925:                 printf("+++Interruption\n");
 1926:             }
 1927:             else
 1928:             {
 1929:                 printf("+++Interrupt\n");
 1930:             }
 1931: 
 1932:             fflush(stdout);
 1933: 
 1934:             (*s_etat_processus).var_volatile_requete_arret = -1;
 1935:             (*s_etat_processus).var_volatile_alarme = -1;
 1936: 
 1937:             exclusion = 0;
 1938:         }
 1939:     }
 1940:     else
 1941:     {
 1942:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 1943:                 != NULL)
 1944:         {
 1945:             envoi_signal_contexte(s_thread_principal, rpl_sigint);
 1946:         }
 1947:     }
 1948: 
 1949:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 1950:     return;
 1951: }
 1952: 
 1953: static inline void
 1954: signal_tstp(struct_processus *s_etat_processus, pid_t pid)
 1955: {
 1956:     struct_processus        *s_thread_principal;
 1957: 
 1958:     verrouillage_gestionnaire_signaux(s_etat_processus);
 1959: 
 1960:     if (pid == getpid())
 1961:     {
 1962:         /*
 1963:          *  0 => fonctionnement normal
 1964:          * -1 => requête
 1965:          *  1 => requête acceptée en attente de traitement
 1966:          */
 1967: 
 1968:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 1969:         {
 1970:             printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
 1971:                     (unsigned long long) pthread_self());
 1972:             fflush(stdout);
 1973:         }
 1974: 
 1975:         if ((*s_etat_processus).var_volatile_processus_pere == 0)
 1976:         {
 1977:             envoi_signal_processus((*s_etat_processus).pid_processus_pere,
 1978:                     rpl_sigtstp, d_faux);
 1979:         }
 1980:         else
 1981:         {
 1982:             (*s_etat_processus).var_volatile_requete_arret2 = -1;
 1983:         }
 1984:     }
 1985:     else
 1986:     {
 1987:         // Envoi d'un signal au thread maître du groupe.
 1988: 
 1989:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 1990:                 != NULL)
 1991:         {
 1992:             envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
 1993:         }
 1994:     }
 1995: 
 1996:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 1997:     return;
 1998: }
 1999: 
 2000: static void
 2001: sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
 2002: {
 2003:     switch((*((volatile int *) arg1)))
 2004:     {
 2005:         case 1:
 2006:             longjmp(contexte_ecriture, -1);
 2007:             break;
 2008: 
 2009:         case 2:
 2010:             longjmp(contexte_impression, -1);
 2011:             break;
 2012:     }
 2013: 
 2014:     return;
 2015: }
 2016: 
 2017: void
 2018: interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
 2019: {
 2020:     if ((urgence == 0) && (routine_recursive != 0))
 2021:     {
 2022:         // On peut tenter de récupérer le dépassement de pile. Si la variable
 2023:         // 'routine_recursive' est non nulle, on récupère l'erreur.
 2024: 
 2025:         sigsegv_leave_handler(sortie_interruption_depassement_pile,
 2026:                 (void *) &routine_recursive, NULL, NULL);
 2027:     }
 2028: 
 2029:     // Ici, la panique est totale et il vaut mieux quitter l'application.
 2030:     interruption3(SIGUSR2);
 2031:     return;
 2032: }
 2033: 
 2034: int
 2035: interruption_violation_access(void *adresse_fautive, int gravite)
 2036: {
 2037:     unsigned char       message[] = "+++System : Trying to catch access "
 2038:                                 "violation\n";
 2039: 
 2040:     static int          compteur_erreur = 0;
 2041: 
 2042:     if ((gravite == 0) && (routine_recursive != 0))
 2043:     {
 2044:         // Il peut s'agir d'un dépassement de pile.
 2045: 
 2046:         sigsegv_leave_handler(sortie_interruption_depassement_pile,
 2047:                 (void *) &routine_recursive, NULL, NULL);
 2048:     }
 2049: 
 2050:     // On est dans une bonne vieille violation d'accès. On essaie
 2051:     // de fermer au mieux l'application.
 2052: 
 2053:     compteur_erreur++;
 2054: 
 2055:     if (compteur_erreur >= 2)
 2056:     {
 2057:         // Erreurs multiples, on arrête l'application.
 2058:         interruption3(SIGSEGV);
 2059:         return(0);
 2060:     }
 2061: 
 2062: #   pragma GCC diagnostic push
 2063: #   pragma GCC diagnostic ignored "-Wunused-result"
 2064: 
 2065:     write(STDERR_FILENO, message, strlen(message));
 2066: 
 2067: #   pragma GCC diagnostic pop
 2068: 
 2069:     if (pid_processus_pere == getpid())
 2070:     {
 2071:         longjmp(contexte_initial, -1);
 2072:         return(1);
 2073:     }
 2074:     else
 2075:     {
 2076:         longjmp(contexte_processus, -1);
 2077:         return(1);
 2078:     }
 2079: 
 2080:     // On renvoie 0 parce qu'on décline toute responsabilité quant à la
 2081:     // suite des événements...
 2082:     return(0);
 2083: }
 2084: 
 2085: // Traitement de rpl_sigstart
 2086: 
 2087: static inline void
 2088: signal_start(struct_processus *s_etat_processus, pid_t pid)
 2089: {
 2090:     struct_processus        *s_thread_principal;
 2091: 
 2092:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2093: 
 2094:     if (pid == getpid())
 2095:     {
 2096:         (*s_etat_processus).demarrage_fils = d_vrai;
 2097:     }
 2098:     else
 2099:     {
 2100:         // Envoi d'un signal au thread maître du groupe.
 2101: 
 2102:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 2103:                 != NULL)
 2104:         {
 2105:             envoi_signal_contexte(s_thread_principal, rpl_sigstart);
 2106:         }
 2107:     }
 2108: 
 2109:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2110:     return;
 2111: }
 2112: 
 2113: // Traitement de rpl_sigcont
 2114: 
 2115: static inline void
 2116: signal_cont(struct_processus *s_etat_processus, pid_t pid)
 2117: {
 2118:     struct_processus        *s_thread_principal;
 2119: 
 2120:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2121: 
 2122:     if (pid == getpid())
 2123:     {
 2124:         (*s_etat_processus).redemarrage_processus = d_vrai;
 2125:     }
 2126:     else
 2127:     {
 2128:         // Envoi d'un signal au thread maître du groupe.
 2129: 
 2130:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 2131:                 != NULL)
 2132:         {
 2133:             envoi_signal_contexte(s_thread_principal, rpl_sigcont);
 2134:         }
 2135:     }
 2136: 
 2137:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2138:     return;
 2139: }
 2140: 
 2141: // Traitement de rpl_sigstop
 2142: 
 2143: static inline void
 2144: signal_stop(struct_processus *s_etat_processus, pid_t pid)
 2145: {
 2146:     struct_processus        *s_thread_principal;
 2147: 
 2148:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2149: 
 2150:     if (pid == getpid())
 2151:     {
 2152:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 2153:         {
 2154:             printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
 2155:                     (unsigned long long) pthread_self());
 2156:             fflush(stdout);
 2157:         }
 2158: 
 2159:         /*
 2160:          * var_globale_traitement_retarde_stop :
 2161:          *  0 -> traitement immédiat
 2162:          *  1 -> traitement retardé (aucun signal reçu)
 2163:          * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
 2164:          */
 2165: 
 2166:         if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
 2167:         {
 2168:             (*s_etat_processus).var_volatile_requete_arret = -1;
 2169:         }
 2170:         else
 2171:         {
 2172:             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
 2173:         }
 2174:     }
 2175:     else
 2176:     {
 2177:         // Envoi d'un signal au thread maître du groupe.
 2178: 
 2179:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 2180:                 != NULL)
 2181:         {
 2182:             envoi_signal_contexte(s_thread_principal, rpl_sigstop);
 2183:         }
 2184:     }
 2185: 
 2186:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2187:     return;
 2188: }
 2189: 
 2190: // Traitement de rpl_siginject
 2191: 
 2192: static inline void
 2193: signal_inject(struct_processus *s_etat_processus, pid_t pid)
 2194: {
 2195:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2196: 
 2197:     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
 2198:     {
 2199:         deverrouillage_gestionnaire_signaux(s_etat_processus);
 2200:         return;
 2201:     }
 2202: 
 2203:     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 2204:     {
 2205:         printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
 2206:                 (unsigned long long) pthread_self());
 2207:         fflush(stdout);
 2208:     }
 2209: 
 2210:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2211:     return;
 2212: }
 2213: 
 2214: 
 2215: static inline void
 2216: signal_urg(struct_processus *s_etat_processus, pid_t pid)
 2217: {
 2218:     struct_processus        *s_thread_principal;
 2219: 
 2220:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2221: 
 2222:     if (pid == getpid())
 2223:     {
 2224:         if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 2225:         {
 2226:             printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
 2227:                     (unsigned long long) pthread_self());
 2228:             fflush(stdout);
 2229:         }
 2230: 
 2231:         (*s_etat_processus).var_volatile_alarme = -1;
 2232:         (*s_etat_processus).var_volatile_requete_arret = -1;
 2233:     }
 2234:     else
 2235:     {
 2236:         // Envoi d'un signal au thread maître du groupe.
 2237: 
 2238:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 2239:                 != NULL)
 2240:         {
 2241:             envoi_signal_contexte(s_thread_principal, rpl_sigurg);
 2242:         }
 2243:     }
 2244: 
 2245:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2246:     return;
 2247: }
 2248: 
 2249: // Traitement de rpl_sigabort
 2250: 
 2251: static inline void
 2252: signal_abort(struct_processus *s_etat_processus, pid_t pid)
 2253: {
 2254:     struct_processus        *s_thread_principal;
 2255: 
 2256:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2257: 
 2258:     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
 2259:     {
 2260:         deverrouillage_gestionnaire_signaux(s_etat_processus);
 2261:         return;
 2262:     }
 2263: 
 2264:     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 2265:     {
 2266:         printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
 2267:                 (unsigned long long) pthread_self());
 2268:         fflush(stdout);
 2269:     }
 2270: 
 2271:     if (pid == getpid())
 2272:     {
 2273:         (*s_etat_processus).arret_depuis_abort = -1;
 2274: 
 2275:         /*
 2276:          * var_globale_traitement_retarde_stop :
 2277:          *  0 -> traitement immédiat
 2278:          *  1 -> traitement retardé (aucun signal reçu)
 2279:          * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
 2280:          */
 2281: 
 2282:         if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
 2283:         {
 2284:             (*s_etat_processus).var_volatile_requete_arret = -1;
 2285:         }
 2286:         else
 2287:         {
 2288:             (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
 2289:         }
 2290:     }
 2291:     else
 2292:     {
 2293:         (*s_etat_processus).arret_depuis_abort = -1;
 2294: 
 2295:         // Envoi d'un signal au thread maître du groupe.
 2296: 
 2297:         if ((s_thread_principal = recherche_thread_principal(getpid()))
 2298:                 != NULL)
 2299:         {
 2300:             envoi_signal_contexte(s_thread_principal, rpl_sigabort);
 2301:         }
 2302:     }
 2303: 
 2304:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2305:     return;
 2306: }
 2307: 
 2308: 
 2309: static inline void
 2310: signal_hup(struct_processus *s_etat_processus, pid_t pid)
 2311: {
 2312:     file                    *fichier;
 2313: 
 2314:     unsigned char           nom[8 + 64 + 1];
 2315: 
 2316:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2317: 
 2318:     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
 2319:     {
 2320:         deverrouillage_gestionnaire_signaux(s_etat_processus);
 2321:         return;
 2322:     }
 2323: 
 2324:     snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
 2325:             (unsigned long long) getpid(),
 2326:             (unsigned long long) pthread_self());
 2327: 
 2328: #   pragma GCC diagnostic push
 2329: #   pragma GCC diagnostic ignored "-Wunused-result"
 2330: 
 2331:     if ((fichier = fopen(nom, "w+")) != NULL)
 2332:     {
 2333:         fclose(fichier);
 2334: 
 2335:         freopen(nom, "w", stdout);
 2336:         freopen(nom, "w", stderr);
 2337:     }
 2338: 
 2339:     freopen("/dev/null", "r", stdin);
 2340: 
 2341: #   pragma GCC diagnostic pop
 2342: 
 2343:     if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
 2344:     {
 2345:         printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
 2346:                 (unsigned long long) pthread_self());
 2347:         fflush(stdout);
 2348:     }
 2349: 
 2350:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2351:     return;
 2352: }
 2353: 
 2354: void
 2355: traitement_exceptions_gsl(const char *reason, const char *file,
 2356:         int line, int gsl_errno)
 2357: {
 2358:     code_erreur_gsl = gsl_errno;
 2359:     envoi_signal_processus(getpid(), rpl_sigexcept, d_faux);
 2360:     return;
 2361: }
 2362: 
 2363: static inline void
 2364: signal_except(struct_processus *s_etat_processus, pid_t pid)
 2365: {
 2366:     verrouillage_gestionnaire_signaux(s_etat_processus);
 2367: 
 2368:     if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
 2369:     {
 2370:         deverrouillage_gestionnaire_signaux(s_etat_processus);
 2371:         return;
 2372:     }
 2373: 
 2374:     (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
 2375:     deverrouillage_gestionnaire_signaux(s_etat_processus);
 2376: 
 2377:     return;
 2378: }
 2379: 
 2380: static inline void
 2381: envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
 2382:         pid_t pid_source)
 2383: {
 2384:     switch(signal)
 2385:     {
 2386:         case rpl_signull:
 2387:             break;
 2388: 
 2389:         case rpl_sigint:
 2390:             signal_int(s_etat_processus, pid_source);
 2391:             break;
 2392: 
 2393:         case rpl_sigterm:
 2394:             signal_term(s_etat_processus, pid_source);
 2395:             break;
 2396: 
 2397:         case rpl_sigstart:
 2398:             signal_start(s_etat_processus, pid_source);
 2399:             break;
 2400: 
 2401:         case rpl_sigcont:
 2402:             signal_cont(s_etat_processus, pid_source);
 2403:             break;
 2404: 
 2405:         case rpl_sigstop:
 2406:             signal_stop(s_etat_processus, pid_source);
 2407:             break;
 2408: 
 2409:         case rpl_sigabort:
 2410:             signal_abort(s_etat_processus, pid_source);
 2411:             break;
 2412: 
 2413:         case rpl_sigurg:
 2414:             signal_urg(s_etat_processus, pid_source);
 2415:             break;
 2416: 
 2417:         case rpl_siginject:
 2418:             signal_inject(s_etat_processus, pid_source);
 2419:             break;
 2420: 
 2421:         case rpl_sigalrm:
 2422:             signal_alrm(s_etat_processus, pid_source);
 2423:             break;
 2424: 
 2425:         case rpl_sighup:
 2426:             signal_hup(s_etat_processus, pid_source);
 2427:             break;
 2428: 
 2429:         case rpl_sigtstp:
 2430:             signal_tstp(s_etat_processus, pid_source);
 2431:             break;
 2432: 
 2433:         case rpl_sigexcept:
 2434:             signal_except(s_etat_processus, pid_source);
 2435:             break;
 2436: 
 2437:         default:
 2438:             if ((*s_etat_processus).langue == 'F')
 2439:             {
 2440:                 printf("+++System : Signal inconnu (%d) !\n", signal);
 2441:             }
 2442:             else
 2443:             {
 2444:                 printf("+++System : Spurious signal (%d) !\n", signal);
 2445:             }
 2446: 
 2447:             break;
 2448:     }
 2449: 
 2450:     return;
 2451: }
 2452: 
 2453: void
 2454: scrutation_interruptions(struct_processus *s_etat_processus)
 2455: {
 2456:     // Interruptions qui arrivent sur le processus depuis un
 2457:     // processus externe.
 2458: 
 2459:     // Les pointeurs de lecture pointent sur les prochains éléments
 2460:     // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
 2461:     // écrire.
 2462: 
 2463:     if (sem_trywait(semaphore_queue_signaux) == 0)
 2464:     {
 2465:         while((*s_queue_signaux).pointeur_lecture !=
 2466:                 (*s_queue_signaux).pointeur_ecriture)
 2467:         {
 2468:             // Il y a un signal en attente dans le segment partagé. On le
 2469:             // traite.
 2470: 
 2471:             envoi_interruptions(s_etat_processus,
 2472:                     (*s_queue_signaux).queue[(*s_queue_signaux)
 2473:                     .pointeur_lecture].signal, (*s_queue_signaux).queue
 2474:                     [(*s_queue_signaux).pointeur_lecture].pid);
 2475:             (*s_queue_signaux).pointeur_lecture =
 2476:                     ((*s_queue_signaux).pointeur_lecture + 1)
 2477:                     % LONGUEUR_QUEUE_SIGNAUX;
 2478: 
 2479: #           ifndef IPCS_SYSV
 2480:             if (msync(s_queue_signaux, sizeof(s_queue_signaux),
 2481:                     MS_ASYNC | MS_INVALIDATE) != 0)
 2482:             {
 2483:                 sem_post(semaphore_queue_signaux);
 2484:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 2485:                 return;
 2486:             }
 2487: #           endif
 2488: 
 2489:             while(sem_wait(semaphore_signalisation) != 0)
 2490:             {
 2491:                 if (errno != EINTR)
 2492:                 {
 2493:                     (*s_etat_processus).erreur_systeme = d_es_processus;
 2494:                     return;
 2495:                 }
 2496:             }
 2497: 
 2498:             if ((*s_queue_signaux).requete_arret == d_vrai)
 2499:             {
 2500:                 break;
 2501:             }
 2502:         }
 2503: 
 2504:         sem_post(semaphore_queue_signaux);
 2505:     }
 2506: 
 2507:     // Interruptions qui arrivent depuis le groupe courant de threads.
 2508: 
 2509:     if (pthread_mutex_trylock(&mutex_liste_threads) == 0)
 2510:     {
 2511:         if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
 2512:         {
 2513:             while((*s_etat_processus).pointeur_signal_lecture !=
 2514:                     (*s_etat_processus).pointeur_signal_ecriture)
 2515:             {
 2516:                 // Il y a un signal dans la queue du thread courant.
 2517:                 // On le traite.
 2518: 
 2519:                 envoi_interruptions(s_etat_processus,
 2520:                         (*s_etat_processus).signaux_en_queue
 2521:                         [(*s_etat_processus).pointeur_signal_lecture],
 2522:                         getpid());
 2523:                 (*s_etat_processus).pointeur_signal_lecture =
 2524:                         ((*s_etat_processus).pointeur_signal_lecture + 1)
 2525:                         % LONGUEUR_QUEUE_SIGNAUX;
 2526: 
 2527:                 while(sem_wait(semaphore_signalisation) != 0)
 2528:                 {
 2529:                     if (errno != EINTR)
 2530:                     {
 2531:                         if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
 2532:                         {
 2533:                             (*s_etat_processus).erreur_systeme = d_es_processus;
 2534:                             return;
 2535:                         }
 2536: 
 2537:                         (*s_etat_processus).erreur_systeme = d_es_processus;
 2538:                         return;
 2539:                     }
 2540:                 }
 2541:             }
 2542: 
 2543:             pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
 2544:         }
 2545: 
 2546:         pthread_mutex_unlock(&mutex_liste_threads);
 2547:     }
 2548: 
 2549:     return;
 2550: }
 2551: 
 2552: 
 2553: /*
 2554: ================================================================================
 2555:   Fonction renvoyant le nom du segment de mémoire partagée en fonction
 2556:   du pid du processus.
 2557: ================================================================================
 2558:   Entrée : Chemin absolue servant de racine, pid du processus
 2559: --------------------------------------------------------------------------------
 2560:   Sortie : NULL ou nom du segment
 2561: --------------------------------------------------------------------------------
 2562:   Effet de bord : Néant
 2563: ================================================================================
 2564: */
 2565: 
 2566: static unsigned char *
 2567: nom_segment(unsigned char *chemin, pid_t pid)
 2568: {
 2569:     unsigned char               *fichier;
 2570: 
 2571: #   ifdef IPCS_SYSV // !POSIX
 2572: #       ifndef OS2 // !OS2
 2573: 
 2574:             if ((fichier = sys_malloc((strlen(chemin) + 1 + 256 + 1) *
 2575:                     sizeof(unsigned char))) == NULL)
 2576:             {
 2577:                 return(NULL);
 2578:             }
 2579: 
 2580:             sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
 2581: #       else // OS2
 2582:             if ((fichier = sys_malloc((10 + 256 + 1) * sizeof(unsigned char)))
 2583:                     == NULL)
 2584:             {
 2585:                 return(NULL);
 2586:             }
 2587: 
 2588:             sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
 2589: #       endif // OS2
 2590: #   else // POSIX
 2591: 
 2592:         if ((fichier = sys_malloc((1 + 256 + 1) *
 2593:                 sizeof(unsigned char))) == NULL)
 2594:         {
 2595:             return(NULL);
 2596:         }
 2597: 
 2598:         sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
 2599: #   endif
 2600: 
 2601:     return(fichier);
 2602: }
 2603: 
 2604: 
 2605: /*
 2606: ================================================================================
 2607:   Fonctions d'envoi d'un signal à un thread ou à un processus.
 2608: ================================================================================
 2609:   Entrée : processus et signal
 2610: --------------------------------------------------------------------------------
 2611:   Sortie : erreur
 2612: --------------------------------------------------------------------------------
 2613:   Effet de bord : Néant
 2614: ================================================================================
 2615: */
 2616: 
 2617: int
 2618: envoi_signal_processus(pid_t pid, enum signaux_rpl signal,
 2619:         logical1 test_ouverture)
 2620: {
 2621: #   ifndef OS2
 2622:         int                         segment;
 2623: #   endif
 2624: 
 2625: #   ifndef IPCS_SYSV
 2626:         sem_t                       *semaphore;
 2627:         sem_t                       *signalisation;
 2628: #   else
 2629:         sem_t                       *semaphore;
 2630:         sem_t                       *signalisation;
 2631: #       ifndef OS2
 2632:             int                     desc;
 2633:             key_t                   clef;
 2634: #       endif
 2635: #   endif
 2636: 
 2637:     struct_queue_signaux            *queue;
 2638: 
 2639:     struct timespec                 attente;
 2640: 
 2641:     unsigned char                   *nom;
 2642: 
 2643:     // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
 2644:     // mémoire puis d'y inscrire le signal à traiter.
 2645: 
 2646:     if (pid == getpid())
 2647:     {
 2648:         // Le signal est envoyé au même processus.
 2649: 
 2650:         if (s_queue_signaux == NULL)
 2651:         {
 2652:             return(1);
 2653:         }
 2654: 
 2655:         while(sem_wait(semaphore_queue_signaux) != 0)
 2656:         {
 2657:             if (errno != EINTR)
 2658:             {
 2659:                 return(1);
 2660:             }
 2661:         }
 2662: 
 2663:         (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
 2664:                 .pid = pid;
 2665:         (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
 2666:                 .signal = signal;
 2667: 
 2668:         (*s_queue_signaux).pointeur_ecriture =
 2669:                 ((*s_queue_signaux).pointeur_ecriture + 1)
 2670:                 % LONGUEUR_QUEUE_SIGNAUX;
 2671: 
 2672: #       ifndef IPCS_SYSV
 2673:         if (msync(s_queue_signaux, sizeof(s_queue_signaux),
 2674:                 MS_ASYNC | MS_INVALIDATE) != 0)
 2675:         {
 2676:             sem_post(semaphore_queue_signaux);
 2677:             return(1);
 2678:         }
 2679: #       endif
 2680: 
 2681:         if (sem_post(semaphore_queue_signaux) != 0)
 2682:         {
 2683:             return(1);
 2684:         }
 2685: 
 2686:         if (sem_post(semaphore_signalisation) != 0)
 2687:         {
 2688:             return(1);
 2689:         }
 2690:     }
 2691:     else
 2692:     {
 2693:         // Le signal est envoyé depuis un processus distinct.
 2694: 
 2695: #       ifdef IPCS_SYSV
 2696:             if ((nom = nom_segment(racine_segment, pid)) == NULL)
 2697:             {
 2698:                 return(1);
 2699:             }
 2700: 
 2701: #           ifndef OS2 // SysV
 2702:                 if (test_ouverture == d_vrai)
 2703:                 {
 2704:                     attente.tv_sec = 0;
 2705:                     attente.tv_nsec = GRANULARITE_us * 1000;
 2706: 
 2707:                     while((desc = open(nom, O_RDWR)) == -1)
 2708:                     {
 2709:                         nanosleep(&attente, NULL);
 2710:                         INCR_GRANULARITE(attente.tv_nsec);
 2711:                     }
 2712:                 }
 2713:                 else
 2714:                 {
 2715:                     if ((desc = open(nom, O_RDWR)) == -1)
 2716:                     {
 2717:                         sys_free(nom);
 2718:                         return(1);
 2719:                     }
 2720:                 }
 2721: 
 2722:                 close(desc);
 2723: 
 2724:                 if ((clef = ftok(nom, 1)) == -1)
 2725:                 {
 2726:                     sys_free(nom);
 2727:                     return(1);
 2728:                 }
 2729: 
 2730:                 sys_free(nom);
 2731: 
 2732:                 if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
 2733:                         == -1)
 2734:                 {
 2735:                     return(1);
 2736:                 }
 2737: 
 2738:                 queue = shmat(segment, NULL, 0);
 2739: #           else // OS/2
 2740:                 if (DosGetNamedSharedMem((PVOID) &queue, nom,
 2741:                         PAG_WRITE | PAG_READ) != 0)
 2742:                 {
 2743:                     sys_free(nom);
 2744:                     return(1);
 2745:                 }
 2746: 
 2747:                 sys_free(nom);
 2748: #           endif
 2749: #       else // POSIX
 2750:             if ((nom = nom_segment(racine_segment, pid)) == NULL)
 2751:             {
 2752:                 return(1);
 2753:             }
 2754: 
 2755:             if (test_ouverture == d_vrai)
 2756:             {
 2757:                 attente.tv_sec = 0;
 2758:                 attente.tv_nsec = GRANULARITE_us * 1000;
 2759: 
 2760:                 while((segment = shm_open(nom, O_RDWR, 0)) == -1)
 2761:                 {
 2762:                     nanosleep(&attente, NULL);
 2763:                     INCR_GRANULARITE(attente.tv_nsec);
 2764:                 }
 2765:             }
 2766:             else
 2767:             {
 2768:                 if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
 2769:                 {
 2770:                     sys_free(nom);
 2771:                     return(1);
 2772:                 }
 2773:             }
 2774: 
 2775:             sys_free(nom);
 2776: 
 2777:             if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
 2778:                     PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
 2779:                     MAP_FAILED)
 2780:             {
 2781:                 close(segment);
 2782:                 return(1);
 2783:             }
 2784: #       endif
 2785: 
 2786:         // À ce moment, le segment de mémoire partagée est projeté
 2787:         // dans l'espace du processus.
 2788: 
 2789:         if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
 2790:         {
 2791: #           ifndef IPCS_SYSV // POSIX
 2792:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 2793:                 {
 2794:                     munmap(queue, sizeof(struct_queue_signaux));
 2795:                     close(segment);
 2796:                     return(1);
 2797:                 }
 2798: 
 2799:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2800:                 {
 2801:                     close(segment);
 2802:                     return(1);
 2803:                 }
 2804: 
 2805:                 close(segment);
 2806: #           else // IPCS_SYSV
 2807: #               ifndef OS2 // SysV
 2808:                     if (shmdt(queue) != 0)
 2809:                     {
 2810:                         return(1);
 2811:                     }
 2812: #               else // OS/2
 2813:                     // Pendant de DosGetNamedSHaredMem()
 2814: #               endif
 2815: #           endif
 2816:             return(1);
 2817:         }
 2818: 
 2819:         if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
 2820:                 == SEM_FAILED)
 2821:         {
 2822: #           ifndef IPCS_SYSV // POSIX
 2823:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 2824:                 {
 2825:                     munmap(queue, sizeof(struct_queue_signaux));
 2826:                     close(segment);
 2827:                     sem_close(semaphore);
 2828:                     return(1);
 2829:                 }
 2830: 
 2831:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2832:                 {
 2833:                     close(segment);
 2834:                     sem_close(semaphore);
 2835:                     return(1);
 2836:                 }
 2837: 
 2838:                 close(segment);
 2839: #           else // IPCS_SYSV
 2840: #               ifndef OS2 // SysV
 2841:                     if (shmdt(queue) != 0)
 2842:                     {
 2843:                         sem_close(semaphore);
 2844:                         return(1);
 2845:                     }
 2846: #               else // OS/2
 2847:                     // Pendant de DosGetNamedSHaredMem()
 2848: #               endif
 2849: #           endif
 2850: 
 2851:             sem_close(semaphore);
 2852:             return(1);
 2853:         }
 2854: 
 2855:         while(sem_wait(semaphore) != 0)
 2856:         {
 2857:             if (errno != EINTR)
 2858:             {
 2859: #               ifndef IPCS_SYSV // POSIX
 2860:                     if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE)
 2861:                             != 0)
 2862:                     {
 2863:                         munmap(queue, sizeof(struct_queue_signaux));
 2864:                         sem_close(semaphore);
 2865:                         sem_close(signalisation);
 2866:                         close(segment);
 2867:                         return(1);
 2868:                     }
 2869: 
 2870:                     if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2871:                     {
 2872:                         sem_close(semaphore);
 2873:                         sem_close(signalisation);
 2874:                         close(segment);
 2875:                         return(1);
 2876:                     }
 2877: 
 2878:                     close(segment);
 2879: #               else // IPCS_SYSV
 2880: #                   ifndef OS2 // SysV
 2881:                         if (shmdt(queue) != 0)
 2882:                         {
 2883:                             sem_close(semaphore);
 2884:                             sem_close(signalisation);
 2885:                             return(1);
 2886:                         }
 2887: #                   else // OS/2
 2888:                         // Pendant de DosGetNamedSHaredMem()
 2889: #                   endif
 2890: #               endif
 2891: 
 2892:                 sem_close(semaphore);
 2893:                 sem_close(signalisation);
 2894:                 return(1);
 2895:             }
 2896:         }
 2897: 
 2898:         (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
 2899:         (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
 2900: 
 2901:         (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
 2902:                 % LONGUEUR_QUEUE_SIGNAUX;
 2903: 
 2904:         if (sem_post(semaphore) != 0)
 2905:         {
 2906: #           ifndef IPCS_SYSV // POSIX
 2907:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 2908:                 {
 2909:                     munmap(queue, sizeof(struct_queue_signaux));
 2910:                     close(segment);
 2911:                     sem_close(semaphore);
 2912:                     sem_close(signalisation);
 2913:                     return(1);
 2914:                 }
 2915: 
 2916:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2917:                 {
 2918:                     close(segment);
 2919:                     sem_close(semaphore);
 2920:                     sem_close(signalisation);
 2921:                     return(1);
 2922:                 }
 2923: 
 2924:                 close(segment);
 2925: #           else // IPCS_SYSV
 2926: #               ifndef OS2 // SysV
 2927:                     if (shmdt(queue) != 0)
 2928:                     {
 2929:                         sem_close(semaphore);
 2930:                         sem_close(signalisation);
 2931:                         return(1);
 2932:                     }
 2933: #               else // OS/2
 2934:                     // Pendant de DosGetNamedSHaredMem()
 2935: #               endif
 2936: #           endif
 2937: 
 2938:             sem_close(semaphore);
 2939:             sem_close(signalisation);
 2940:             return(1);
 2941:         }
 2942: 
 2943:         if (sem_close(semaphore) != 0)
 2944:         {
 2945: #           ifndef IPCS_SYSV // POSIX
 2946:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 2947:                 {
 2948:                     munmap(queue, sizeof(struct_queue_signaux));
 2949:                     close(segment);
 2950:                     sem_close(signalisation);
 2951:                     return(1);
 2952:                 }
 2953: 
 2954:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2955:                 {
 2956:                     close(segment);
 2957:                     sem_close(signalisation);
 2958:                     return(1);
 2959:                 }
 2960: 
 2961:                 close(segment);
 2962: #           else // IPCS_SYSV
 2963: #               ifndef OS2 // SysV
 2964:                     if (shmdt(queue) != 0)
 2965:                     {
 2966:                         sem_close(signalisation);
 2967:                         return(1);
 2968:                     }
 2969: #               else // OS/2
 2970:                     // Pendant de DosGetNamedSHaredMem()
 2971: #               endif
 2972: #           endif
 2973: 
 2974:             sem_close(signalisation);
 2975:             return(1);
 2976:         }
 2977: 
 2978:         if (sem_post(signalisation) != 0)
 2979:         {
 2980: #           ifndef IPCS_SYSV // POSIX
 2981:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 2982:                 {
 2983:                     munmap(queue, sizeof(struct_queue_signaux));
 2984:                     close(segment);
 2985:                     sem_close(signalisation);
 2986:                     return(1);
 2987:                 }
 2988: 
 2989:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 2990:                 {
 2991:                     close(segment);
 2992:                     sem_close(signalisation);
 2993:                     return(1);
 2994:                 }
 2995: 
 2996:                 close(segment);
 2997: #           else // IPCS_SYSV
 2998: #               ifndef OS2 // SysV
 2999:                     if (shmdt(queue) != 0)
 3000:                     {
 3001:                         sem_close(signalisation);
 3002:                         return(1);
 3003:                     }
 3004: #               else // OS/2
 3005:                     // Pendant de DosGetNamedSHaredMem()
 3006: #               endif
 3007: #           endif
 3008: 
 3009:             sem_close(signalisation);
 3010:             return(1);
 3011:         }
 3012: 
 3013:         if (sem_close(signalisation) != 0)
 3014:         {
 3015: #           ifndef IPCS_SYSV // POSIX
 3016:                 if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 3017:                 {
 3018:                     munmap(queue, sizeof(struct_queue_signaux));
 3019:                     close(segment);
 3020:                     return(1);
 3021:                 }
 3022: 
 3023:                 if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 3024:                 {
 3025:                     close(segment);
 3026:                     return(1);
 3027:                 }
 3028: 
 3029:                 close(segment);
 3030: #           else // IPCS_SYSV
 3031: #               ifndef OS2 // SysV
 3032:                     if (shmdt(queue) != 0)
 3033:                     {
 3034:                         return(1);
 3035:                     }
 3036: #               else // OS/2
 3037:                     // Pendant de DosGetNamedSHaredMem()
 3038: #               endif
 3039: #           endif
 3040: 
 3041:             return(1);
 3042:         }
 3043: 
 3044: #       ifndef IPCS_SYSV // POSIX
 3045:             if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
 3046:             {
 3047:                 munmap(queue, sizeof(struct_queue_signaux));
 3048:                 close(segment);
 3049:                 return(1);
 3050:             }
 3051: 
 3052:             if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
 3053:             {
 3054:                 close(segment);
 3055:                 return(1);
 3056:             }
 3057: 
 3058:             close(segment);
 3059: #       else // IPCS_SYSV
 3060: #           ifndef OS2 // SysV
 3061:                 if (shmdt(queue) != 0)
 3062:                 {
 3063:                     return(1);
 3064:                 }
 3065: #           else // OS/2
 3066:                 // Pendant de DosGetNamedSHaredMem()
 3067: #           endif
 3068: #       endif
 3069:     }
 3070: 
 3071:     return(0);
 3072: }
 3073: 
 3074: int
 3075: envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
 3076: {
 3077:     // Un signal est envoyé d'un thread à un autre thread du même processus.
 3078: 
 3079:     volatile struct_liste_chainee_volatile  *l_element_courant;
 3080: 
 3081:     struct_processus                        *s_etat_processus;
 3082: 
 3083:     if (pthread_mutex_lock(&mutex_liste_threads) != 0)
 3084:     {
 3085:         return(1);
 3086:     }
 3087: 
 3088:     l_element_courant = liste_threads;
 3089: 
 3090:     while(l_element_courant != NULL)
 3091:     {
 3092:         if (((*((struct_thread *) (*l_element_courant).donnee)).pid
 3093:                 == getpid()) && (pthread_equal((*((struct_thread *)
 3094:                 (*l_element_courant).donnee)).tid, tid) != 0))
 3095:         {
 3096:             break;
 3097:         }
 3098: 
 3099:         l_element_courant = (*l_element_courant).suivant;
 3100:     }
 3101: 
 3102:     if (l_element_courant == NULL)
 3103:     {
 3104:         pthread_mutex_unlock(&mutex_liste_threads);
 3105:         return(1);
 3106:     }
 3107: 
 3108:     s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
 3109:             .s_etat_processus;
 3110: 
 3111:     if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
 3112:     {
 3113:         pthread_mutex_unlock(&mutex_liste_threads);
 3114:         return(1);
 3115:     }
 3116: 
 3117:     (*s_etat_processus).signaux_en_queue
 3118:             [(*s_etat_processus).pointeur_signal_ecriture] = signal;
 3119:     (*s_etat_processus).pointeur_signal_ecriture =
 3120:             ((*s_etat_processus).pointeur_signal_ecriture + 1)
 3121:             % LONGUEUR_QUEUE_SIGNAUX;
 3122: 
 3123:     if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
 3124:     {
 3125:         pthread_mutex_unlock(&mutex_liste_threads);
 3126:         return(1);
 3127:     }
 3128: 
 3129:     if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
 3130:     {
 3131:         return(1);
 3132:     }
 3133: 
 3134:     if (sem_post(semaphore_signalisation) != 0)
 3135:     {
 3136:         return(1);
 3137:     }
 3138: 
 3139:     return(0);
 3140: }
 3141: 
 3142: int
 3143: envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
 3144:         enum signaux_rpl signal)
 3145: {
 3146:     pthread_mutex_lock(&((*s_etat_processus_a_signaler).mutex_signaux));
 3147:     (*s_etat_processus_a_signaler).signaux_en_queue
 3148:             [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =
 3149:             signal;
 3150:     (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
 3151:             ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
 3152:             % LONGUEUR_QUEUE_SIGNAUX;
 3153:     pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
 3154: 
 3155:     if (sem_post(semaphore_signalisation) != 0)
 3156:     {
 3157:         return(1);
 3158:     }
 3159: 
 3160:     return(0);
 3161: }
 3162: 
 3163: 
 3164: /*
 3165: ================================================================================
 3166:   Fonction créant un segment de mémoire partagée destiné à contenir
 3167:   la queue des signaux.
 3168: ================================================================================
 3169:   Entrée : structure de description du processus
 3170: --------------------------------------------------------------------------------
 3171:   Sortie : Néant
 3172: --------------------------------------------------------------------------------
 3173:   Effet de bord : Néant
 3174: ================================================================================
 3175: */
 3176: 
 3177: void
 3178: creation_queue_signaux(struct_processus *s_etat_processus)
 3179: {
 3180:     pthread_attr_t                  attributs;
 3181: 
 3182:     unsigned char                   *nom;
 3183: 
 3184:     racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
 3185: 
 3186: #   ifndef IPCS_SYSV // POSIX
 3187:         if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
 3188:                 getpid())) == NULL)
 3189:         {
 3190:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3191:             return;
 3192:         }
 3193: 
 3194:         if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
 3195:                 S_IRUSR | S_IWUSR)) == -1)
 3196:         {
 3197:             if (errno != EEXIST)
 3198:             {
 3199:                 sys_free(nom);
 3200:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3201:                 return;
 3202:             }
 3203: 
 3204:             if ((*s_etat_processus).langue == 'F')
 3205:             {
 3206:                 printf("+++Attention : Le segment de mémoire %s préexiste !\n",
 3207:                         nom);
 3208:             }
 3209:             else
 3210:             {
 3211:                 printf("+++Warning: %s memory segment preexists!\n", nom);
 3212:             }
 3213: 
 3214:             if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_TRUNC,
 3215:                     S_IRUSR | S_IWUSR)) == -1)
 3216:             {
 3217:                 sys_free(nom);
 3218:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3219:                 return;
 3220:             }
 3221:         }
 3222: 
 3223:         if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
 3224:         {
 3225:             sys_free(nom);
 3226:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3227:             return;
 3228:         }
 3229: 
 3230:         s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
 3231:                 PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
 3232: 
 3233:         if (((void *) s_queue_signaux) == ((void *) -1))
 3234:         {
 3235:             if (shm_unlink(nom) == -1)
 3236:             {
 3237:                 sys_free(nom);
 3238:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3239:                 return;
 3240:             }
 3241: 
 3242:             sys_free(nom);
 3243:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3244:             return;
 3245:         }
 3246: 
 3247:         sys_free(nom);
 3248: 
 3249:         if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
 3250:                 == SEM_FAILED)
 3251:         {
 3252:             (*s_etat_processus).erreur_systeme = d_es_processus;
 3253:             return;
 3254:         }
 3255: 
 3256:         if ((semaphore_signalisation = sem_init2(0, getpid(),
 3257:                 SEM_SIGNALISATION)) == SEM_FAILED)
 3258:         {
 3259:             (*s_etat_processus).erreur_systeme = d_es_processus;
 3260:             return;
 3261:         }
 3262: 
 3263:         if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
 3264:                 SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
 3265:         {
 3266:             (*s_etat_processus).erreur_systeme = d_es_processus;
 3267:             return;
 3268:         }
 3269: 
 3270:         (*s_queue_signaux).pointeur_lecture = 0;
 3271:         (*s_queue_signaux).pointeur_ecriture = 0;
 3272: 
 3273:         (*s_queue_signaux).requete_arret = d_faux;
 3274: 
 3275:         if (msync(s_queue_signaux, sizeof(struct_queue_signaux),
 3276:                 MS_ASYNC | MS_INVALIDATE) != 0)
 3277:         {
 3278:             (*s_etat_processus).erreur_systeme = d_es_processus;
 3279:             return;
 3280:         }
 3281: #   else // IPCS_SYSV
 3282: #       ifndef OS2
 3283:             int                             segment;
 3284:             int                             support;
 3285: 
 3286:             key_t                           clef;
 3287: 
 3288:             // Création d'un segment de données associé au PID du processus
 3289:             // courant
 3290: 
 3291:             if ((nom = nom_segment((*s_etat_processus)
 3292:                     .chemin_fichiers_temporaires, getpid())) == NULL)
 3293:             {
 3294:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3295:                 return;
 3296:             }
 3297: 
 3298:             if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
 3299:                     S_IRUSR | S_IWUSR)) == -1)
 3300:             {
 3301:                 (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
 3302:                 return;
 3303:             }
 3304: 
 3305:             if ((clef = ftok(nom, 1)) == -1)
 3306:             {
 3307:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3308:                 return;
 3309:             }
 3310: 
 3311:             close(support);
 3312:             sys_free(nom);
 3313: 
 3314:             if ((segment = shmget(clef, sizeof(struct_queue_signaux),
 3315:                     IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
 3316:             {
 3317:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3318:                 return;
 3319:             }
 3320: 
 3321:             s_queue_signaux = shmat(segment, NULL, 0);
 3322:             f_queue_signaux = segment;
 3323: 
 3324:             if (((void *) s_queue_signaux) == ((void *) -1))
 3325:             {
 3326:                 if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
 3327:                 {
 3328:                     (*s_etat_processus).erreur_systeme =
 3329:                             d_es_allocation_memoire;
 3330:                     return;
 3331:                 }
 3332: 
 3333:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3334:                 return;
 3335:             }
 3336: 
 3337:             if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
 3338:                     == SEM_FAILED)
 3339:             {
 3340:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3341:                 return;
 3342:             }
 3343: 
 3344:             if ((semaphore_signalisation = sem_init2(0, getpid(),
 3345:                     SEM_SIGNALISATION)) == SEM_FAILED)
 3346:             {
 3347:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3348:                 return;
 3349:             }
 3350: 
 3351:             if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
 3352:                     SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
 3353:             {
 3354:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3355:                 return;
 3356:             }
 3357: 
 3358:             (*s_queue_signaux).pointeur_lecture = 0;
 3359:             (*s_queue_signaux).pointeur_ecriture = 0;
 3360:             (*s_queue_signaux).requete_arret = d_faux;
 3361: #       else // OS/2
 3362:             if ((nom = nom_segment(NULL, getpid())) == NULL)
 3363:             {
 3364:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3365:                 return;
 3366:             }
 3367: 
 3368:             if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
 3369:                     sizeof(struct_queue_signaux),
 3370:                     PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
 3371:             {
 3372:                 sys_free(nom);
 3373:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3374:                 return;
 3375:             }
 3376: 
 3377:             sys_free(nom);
 3378: 
 3379:             sem_init(&((*s_queue_signaux).semaphore), 1, 1);
 3380:             sem_init(&((*s_queue_signaux).signalisation), 1, 0);
 3381:             sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
 3382: 
 3383:             (*s_queue_signaux).pointeur_lecture = 0;
 3384:             (*s_queue_signaux).pointeur_ecriture = 0;
 3385:             (*s_queue_signaux).requete_arret = d_faux;
 3386: #       endif
 3387: #   endif
 3388: 
 3389:     // Lancement du thread de récupération des signaux.
 3390: 
 3391:     if (pthread_attr_init(&attributs) != 0)
 3392:     {
 3393:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3394:         return;
 3395:     }
 3396: 
 3397:     if (pthread_attr_setdetachstate(&attributs,
 3398:             PTHREAD_CREATE_JOINABLE) != 0)
 3399:     {
 3400:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3401:         return;
 3402:     }
 3403: 
 3404: #   ifdef SCHED_OTHER
 3405:     if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0)
 3406:     {
 3407:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3408:         return;
 3409:     }
 3410: #   endif
 3411: 
 3412: #   ifdef PTHREAD_EXPLICIT_SCHED
 3413:     if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0)
 3414:     {
 3415:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3416:         return;
 3417:     }
 3418: #   endif
 3419: 
 3420: #   ifdef PTHREAD_SCOPE_SYSTEM
 3421:     if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0)
 3422:     {
 3423:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3424:         return;
 3425:     }
 3426: #   endif
 3427: 
 3428:     if (pthread_attr_destroy(&attributs) != 0)
 3429:     {
 3430:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3431:         return;
 3432:     }
 3433: 
 3434:     if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
 3435:             thread_surveillance_signaux, s_etat_processus) != 0)
 3436:     {
 3437:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3438:         return;
 3439:     }
 3440: 
 3441:     (*s_queue_signaux).controle = getpid();
 3442: 
 3443: #   ifndef IPCS_SYSV
 3444:     if (msync(s_queue_signaux, sizeof(s_queue_signaux),
 3445:             MS_ASYNC | MS_INVALIDATE) != 0)
 3446:     {
 3447:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3448:         return;
 3449:     }
 3450: #           endif
 3451: 
 3452:     if (lancement_thread_signaux(s_etat_processus) == d_erreur)
 3453:     {
 3454:         (*s_etat_processus).erreur_systeme = d_es_processus;
 3455:         return;
 3456:     }
 3457: 
 3458:     return;
 3459: }
 3460: 
 3461: 
 3462: /*
 3463: ================================================================================
 3464:   Fonction libérant le segment de mémoire partagée destiné à contenir
 3465:   la queue des signaux.
 3466: ================================================================================
 3467:   Entrée : structure de description du processus
 3468: --------------------------------------------------------------------------------
 3469:   Sortie : Néant
 3470: --------------------------------------------------------------------------------
 3471:   Effet de bord : Néant
 3472: ================================================================================
 3473: */
 3474: 
 3475: void
 3476: liberation_queue_signaux(struct_processus *s_etat_processus)
 3477: {
 3478: #   ifdef IPCS_SYSV // SystemV
 3479: #       ifndef OS2
 3480:             if (shmdt(s_queue_signaux) == -1)
 3481:             {
 3482:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3483:                 return;
 3484:             }
 3485: #       else // OS/2
 3486: #       endif
 3487: #   else // POSIX
 3488:         sem_close(semaphore_queue_signaux);
 3489:         sem_close(semaphore_signalisation);
 3490:         sem_close(semaphore_arret_signalisation);
 3491: 
 3492:         if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
 3493:         {
 3494:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3495:             return;
 3496:         }
 3497: 
 3498:         close(f_queue_signaux);
 3499: #   endif
 3500: 
 3501:     return;
 3502: }
 3503: 
 3504: 
 3505: /*
 3506: ================================================================================
 3507:   Fonction détruisant le segment de mémoire partagée destiné à contenir
 3508:   la queue des signaux.
 3509: ================================================================================
 3510:   Entrée : structure de description du processus
 3511: --------------------------------------------------------------------------------
 3512:   Sortie : Néant
 3513: --------------------------------------------------------------------------------
 3514:   Effet de bord : Néant
 3515: ================================================================================
 3516: */
 3517: 
 3518: void
 3519: destruction_queue_signaux(struct_processus *s_etat_processus)
 3520: {
 3521: #   ifndef OS2
 3522:         unsigned char       *nom;
 3523: #   endif
 3524: 
 3525:     sem_wait(semaphore_arret_signalisation);
 3526:     (*s_queue_signaux).requete_arret = d_vrai;
 3527: 
 3528: #   ifndef IPCS_SYSV
 3529:     msync(s_queue_signaux, sizeof(s_queue_signaux), MS_ASYNC | MS_INVALIDATE);
 3530: #   endif
 3531: 
 3532:     sem_post(semaphore_arret_signalisation);
 3533: 
 3534:     // Incrémenter le sémaphore pour être sûr de le débloquer.
 3535: 
 3536:     sem_post(semaphore_signalisation);
 3537:     pthread_join((*s_queue_signaux).thread_signaux, NULL);
 3538:     arret_thread_signaux(s_etat_processus);
 3539: 
 3540: #   ifdef IPCS_SYSV // SystemV
 3541: #       ifndef OS2
 3542:             // Il faut commencer par éliminer le sémaphore.
 3543: 
 3544:             if (semctl((*semaphore_queue_signaux).sem, 0, IPC_RMID) == -1)
 3545:             {
 3546:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3547:                 return;
 3548:             }
 3549: 
 3550:             unlink((*semaphore_queue_signaux).path);
 3551:             sys_free((*semaphore_queue_signaux).path);
 3552: 
 3553:             if (semctl((*semaphore_signalisation).sem, 0, IPC_RMID) == -1)
 3554:             {
 3555:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3556:                 return;
 3557:             }
 3558: 
 3559:             unlink((*semaphore_signalisation).path);
 3560:             sys_free((*semaphore_signalisation).path);
 3561: 
 3562:             if (semctl((*semaphore_arret_signalisation).sem, 0, IPC_RMID) == -1)
 3563:             {
 3564:                 (*s_etat_processus).erreur_systeme = d_es_processus;
 3565:                 return;
 3566:             }
 3567: 
 3568:             unlink((*semaphore_arret_signalisation).path);
 3569:             sys_free((*semaphore_arret_signalisation).path);
 3570: 
 3571:             if (shmdt(s_queue_signaux) == -1)
 3572:             {
 3573:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3574:                 return;
 3575:             }
 3576: 
 3577:             if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
 3578:             {
 3579:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3580:                 return;
 3581:             }
 3582: 
 3583:             if ((nom = nom_segment((*s_etat_processus)
 3584:                     .chemin_fichiers_temporaires, getpid())) == NULL)
 3585:             {
 3586:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3587:                 return;
 3588:             }
 3589: 
 3590:             unlink(nom);
 3591:             sys_free(nom);
 3592: #       else
 3593:             sem_close(&((*s_queue_signaux).semaphore));
 3594:             sem_destroy(&((*s_queue_signaux).semaphore));
 3595: 
 3596:             sem_close(&((*s_queue_signaux).signalisation));
 3597:             sem_destroy(&((*s_queue_signaux).signalisation));
 3598: 
 3599:             sem_close(&((*s_queue_signaux).arret_signalisation));
 3600:             sem_destroy(&((*s_queue_signaux).arret_signalisation));
 3601: 
 3602:             if (DosFreeMem(s_queue_signaux) != 0)
 3603:             {
 3604:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3605:                 return;
 3606:             }
 3607: #       endif
 3608: #   else // POSIX
 3609:         sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
 3610:         sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
 3611:         sem_destroy2(semaphore_arret_signalisation, getpid(),
 3612:                 SEM_ARRET_SIGNALISATION);
 3613: 
 3614:         if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
 3615:         {
 3616:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3617:             return;
 3618:         }
 3619: 
 3620:         if ((nom = nom_segment(NULL, getpid())) == NULL)
 3621:         {
 3622:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3623:             return;
 3624:         }
 3625: 
 3626:         close(f_queue_signaux);
 3627: 
 3628:         if (shm_unlink(nom) != 0)
 3629:         {
 3630:             sys_free(nom);
 3631:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 3632:             return;
 3633:         }
 3634: 
 3635:         sys_free(nom);
 3636: #   endif
 3637: 
 3638:     return;
 3639: }
 3640: 
 3641: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>