File:  [local] / rpl / src / interruptions.c
Revision 1.201: download - view: text, annotated - select for diffs - revision graph
Sat Feb 9 13:36:42 2019 UTC (5 years, 2 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Patches pour gérer proprement les sémaphores et les mutexes dans
un programme multithreadé.

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

CVSweb interface <joel.bertrand@systella.fr>