File:  [local] / rpl / src / interruptions.c
Revision 1.189: download - view: text, annotated - select for diffs - revision graph
Tue Oct 11 11:58:22 2016 UTC (7 years, 6 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Patch pour Cygwin64.

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

CVSweb interface <joel.bertrand@systella.fr>