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>