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