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