File:  [local] / rpl / src / interruptions.c
Revision 1.180: download - view: text, annotated - select for diffs - revision graph
Wed Jul 20 16:23:59 2016 UTC (7 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Tentative de correction d'un deadlock dans pthread_exit().

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

CVSweb interface <joel.bertrand@systella.fr>