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