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