File:  [local] / rpl / src / interruptions.c
Revision 1.202: download - view: text, annotated - select for diffs - revision graph
Mon Feb 11 06:18:20 2019 UTC (5 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Corrections de mutexes et sémaphores pour les programmes multithreadés.

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

CVSweb interface <joel.bertrand@systella.fr>