File:  [local] / rpl / src / interruptions.c
Revision 1.166: download - view: text, annotated - select for diffs - revision graph
Wed Mar 9 17:49:12 2016 UTC (8 years, 1 month ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction d'un bug sournois dans la gestion des processus détachés.
Ce patch ne résout pas le problème (rafale de SIGALRM qui bloque
le lancement du processus fils) mais corrige des problèmes mineurs connexes,
typiquement des race conditions.

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

CVSweb interface <joel.bertrand@systella.fr>