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