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_signalisation);
110:
111: nombre_signaux_envoyes = 0;
112:
113: // Dans un premier temps, on verrouille la queue des signaux
114: // affectée au processus courant pour vérifier s'il y a quelque
115: // chose à traiter.
116:
117: while((ios = sem_wait(semaphore_queue_signaux)) != 0)
118: {
119: if (errno != EINTR)
120: {
121: (*s_etat_processus).erreur_systeme = d_es_processus;
122: }
123: }
124:
125: if ((*s_queue_signaux).pointeur_lecture !=
126: (*s_queue_signaux).pointeur_ecriture)
127: {
128: // Attention : raise() envoit le signal au thread appelant !
129: // kill() l'envoie au processus appelant, donc dans notre
130: // cas à un thread aléatoire du processus, ce qui nous
131: // convient tout à fait puisqu'il s'agit de débloquer les
132: // appels système lents.
133:
134: nombre_signaux_envoyes++;
135: kill(getpid(), SIGALRM);
136: sched_yield();
137: }
138:
139: sem_post(semaphore_queue_signaux);
140: sem_post(semaphore_arret_signalisation);
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: (*s_etat_processus).erreur_systeme = d_es_processus;
1528: return(d_erreur);
1529: }
1530:
1531: pipe_signaux = (*s_etat_processus).pipe_signaux[1];
1532:
1533: if (pthread_attr_init(&attributs) != 0)
1534: {
1535: (*s_etat_processus).erreur_systeme = d_es_processus;
1536: return(d_erreur);
1537: }
1538:
1539: if (pthread_attr_setdetachstate(&attributs, PTHREAD_CREATE_JOINABLE) != 0)
1540: {
1541: (*s_etat_processus).erreur_systeme = d_es_processus;
1542: return(d_erreur);
1543: }
1544:
1545: if (pthread_create(&((*s_etat_processus).thread_signaux), &attributs,
1546: thread_signaux, s_etat_processus) != 0)
1547: {
1548: (*s_etat_processus).erreur_systeme = d_es_processus;
1549: return(d_erreur);
1550: }
1551:
1552: if (pthread_attr_destroy(&attributs) != 0)
1553: {
1554: (*s_etat_processus).erreur_systeme = d_es_processus;
1555: return(d_erreur);
1556: }
1557:
1558: return(d_absence_erreur);
1559: }
1560:
1561: logical1
1562: arret_thread_signaux(struct_processus *s_etat_processus)
1563: {
1564: unsigned char signal;
1565: ssize_t n;
1566:
1567: signal = (unsigned char ) (rpl_sigmax & 0xFF);
1568:
1569: do
1570: {
1571: n = write_atomic(s_etat_processus, (*s_etat_processus).pipe_signaux[1],
1572: &signal, sizeof(signal));
1573:
1574: if (n < 0)
1575: {
1576: return(d_erreur);
1577: }
1578: } while(n != 1);
1579:
1580: pthread_join((*s_etat_processus).thread_signaux, NULL);
1581:
1582: close((*s_etat_processus).pipe_signaux[1]);
1583: return(d_absence_erreur);
1584: }
1585:
1586: void *
1587: thread_signaux(void *argument)
1588: {
1589: int *pipe;
1590:
1591: sigset_t masque;
1592:
1593: struct pollfd fds;
1594:
1595: struct_processus *s_etat_processus;
1596:
1597: unsigned char signal;
1598:
1599: s_etat_processus = (struct_processus *) argument;
1600: pipe = (*s_etat_processus).pipe_signaux;
1601: fds.fd = pipe[0];
1602: fds.events = POLLIN;
1603:
1604: sigfillset(&masque);
1605: pthread_sigmask(SIG_BLOCK, &masque, NULL);
1606:
1607: do
1608: {
1609: fds.revents = 0;
1610:
1611: while(poll(&fds, 1, -1) == -1)
1612: {
1613: if (errno != EINTR)
1614: {
1615: close((*s_etat_processus).pipe_signaux[0]);
1616: pthread_exit(NULL);
1617: }
1618: }
1619:
1620: if (read_atomic(s_etat_processus, fds.fd, &signal, 1) != 1)
1621: {
1622: close((*s_etat_processus).pipe_signaux[0]);
1623: pthread_exit(NULL);
1624: }
1625:
1626: if (signal != (0xFF & rpl_sigmax))
1627: {
1628: envoi_signal_processus(getpid(), signal, d_faux);
1629: // Un signal SIGALRM est envoyé par le thread de surveillance
1630: // des signaux jusqu'à ce que les signaux soient tous traités.
1631: }
1632: } while(signal != (0xFF & rpl_sigmax));
1633:
1634: close((*s_etat_processus).pipe_signaux[0]);
1635: pthread_exit(NULL);
1636: }
1637:
1638:
1639: static inline void
1640: _write(int fd, const void *buf, size_t count)
1641: {
1642: ssize_t ios;
1643:
1644: while((ios = write(fd, buf, count)) == -1)
1645: {
1646: if (errno != EINTR)
1647: {
1648: break;
1649: }
1650: }
1651:
1652: return;
1653: }
1654:
1655:
1656: // Récupération des signaux
1657: // - SIGINT (arrêt au clavier)
1658: // - SIGTERM (signal d'arrêt en provenance du système)
1659:
1660: void
1661: interruption1(int signal)
1662: {
1663: unsigned char signal_tronque;
1664:
1665: test_signal(signal);
1666:
1667: switch(signal)
1668: {
1669: case SIGINT:
1670: signal_tronque = (unsigned char) (rpl_sigint & 0xFF);
1671: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1672: break;
1673:
1674: case SIGTERM:
1675: signal_tronque = (unsigned char) (rpl_sigterm & 0xFF);
1676: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1677: break;
1678:
1679: case SIGUSR1:
1680: signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
1681: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1682: break;
1683:
1684: default:
1685: // SIGALRM
1686: break;
1687: }
1688:
1689: return;
1690: }
1691:
1692: // Récupération des signaux
1693: // - SIGFSTP
1694: //
1695: // ATTENTION :
1696: // Le signal SIGFSTP provient de la mort du processus de contrôle.
1697: // Sous certains systèmes (Linux...), la mort du terminal de contrôle
1698: // se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
1699: // (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
1700: // non initialisée (pointeur NULL) issue de TERMIO.
1701:
1702: void
1703: interruption2(int signal)
1704: {
1705: unsigned char signal_tronque;
1706:
1707: test_signal(signal);
1708:
1709: signal_tronque = (unsigned char) (rpl_sigtstp & 0xFF);
1710: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1711:
1712: return;
1713: }
1714:
1715: void
1716: interruption3(int signal)
1717: {
1718: // Si on passe par ici, c'est qu'il est impossible de récupérer
1719: // l'erreur d'accès à la mémoire. On sort donc du programme quitte à
1720: // ce qu'il reste des processus orphelins.
1721:
1722: unsigned char message_1[] = "+++System : Uncaught access violation\n"
1723: "+++System : Aborting !\n";
1724: unsigned char message_2[] = "+++System : Stack overflow\n"
1725: "+++System : Aborting !\n";
1726:
1727: test_signal(signal);
1728:
1729: if (pid_processus_pere == getpid())
1730: {
1731: kill(pid_processus_pere, SIGUSR1);
1732: }
1733:
1734: # pragma GCC diagnostic push
1735: # pragma GCC diagnostic ignored "-Wunused-result"
1736:
1737: if (signal != SIGUSR2)
1738: {
1739: write(STDERR_FILENO, message_1, strlen(message_1));
1740: }
1741: else
1742: {
1743: write(STDERR_FILENO, message_2, strlen(message_2));
1744: }
1745:
1746: # pragma GCC diagnostic pop
1747:
1748: _exit(EXIT_FAILURE);
1749: }
1750:
1751: // Récupération des signaux
1752: // - SIGHUP
1753:
1754: void
1755: interruption4(int signal)
1756: {
1757: unsigned char signal_tronque;
1758:
1759: test_signal(signal);
1760:
1761: signal_tronque = (unsigned char) (rpl_sighup & 0xFF);
1762: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1763:
1764: return;
1765: }
1766:
1767: // Récupération des signaux
1768: // - SIGPIPE
1769:
1770: void
1771: interruption5(int signal)
1772: {
1773: unsigned char message[] = "+++System : SIGPIPE\n"
1774: "+++System : Aborting !\n";
1775: unsigned char signal_tronque;
1776:
1777: test_signal(signal);
1778:
1779: # pragma GCC diagnostic push
1780: # pragma GCC diagnostic ignored "-Wunused-result"
1781:
1782: if (pid_processus_pere == getpid())
1783: {
1784: signal_tronque = (unsigned char) (rpl_sigalrm & 0xFF);
1785: _write(pipe_signaux, &signal_tronque, sizeof(signal_tronque));
1786: }
1787:
1788: write(STDERR_FILENO, message, strlen(message));
1789:
1790: # pragma GCC diagnostic pop
1791:
1792: return;
1793: }
1794:
1795: inline static void
1796: signal_alrm(struct_processus *s_etat_processus, pid_t pid)
1797: {
1798: struct_processus *s_thread_principal;
1799:
1800: verrouillage_gestionnaire_signaux(s_etat_processus);
1801:
1802: if (pid == getpid())
1803: {
1804: // Si pid est égal à getpid(), le signal à traiter est issu
1805: // du même processus que celui qui va le traiter, mais d'un thread
1806: // différent.
1807:
1808: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1809: {
1810: printf("[%d] RPL/SIGALRM (thread %llu)\n", (int) getpid(),
1811: (unsigned long long) pthread_self());
1812: fflush(stdout);
1813: }
1814:
1815: if ((*s_etat_processus).pid_processus_pere != getpid())
1816: {
1817: // On n'est pas dans le processus père, on remonte le signal.
1818: envoi_signal_processus((*s_etat_processus).pid_processus_pere,
1819: rpl_sigalrm, d_faux);
1820: }
1821: else
1822: {
1823: // On est dans le processus père, on effectue un arrêt d'urgence.
1824: (*s_etat_processus).var_volatile_alarme = -1;
1825: (*s_etat_processus).var_volatile_requete_arret = -1;
1826: }
1827: }
1828: else
1829: {
1830: // Le signal est issu d'un processus différent. On recherche le
1831: // thread principal pour remonter le signal.
1832:
1833: if ((s_thread_principal = recherche_thread_principal(getpid()))
1834: != NULL)
1835: {
1836: envoi_signal_contexte(s_thread_principal, rpl_sigalrm);
1837: }
1838: }
1839:
1840: deverrouillage_gestionnaire_signaux(s_etat_processus);
1841: return;
1842: }
1843:
1844: inline static void
1845: signal_term(struct_processus *s_etat_processus, pid_t pid)
1846: {
1847: struct_processus *s_thread_principal;
1848: pthread_mutex_t exclusion = PTHREAD_MUTEX_INITIALIZER;
1849:
1850: verrouillage_gestionnaire_signaux(s_etat_processus);
1851:
1852: if (pid == getpid())
1853: {
1854: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1855: {
1856: printf("[%d] RPL/SIGTERM (thread %llu)\n", (int) getpid(),
1857: (unsigned long long) pthread_self());
1858: fflush(stdout);
1859: }
1860:
1861: if ((*s_etat_processus).pid_processus_pere != getpid())
1862: {
1863: envoi_signal_processus((*s_etat_processus).pid_processus_pere,
1864: rpl_sigterm, d_faux);
1865: }
1866: else
1867: {
1868: (*s_etat_processus).var_volatile_traitement_sigint = -1;
1869:
1870: pthread_mutex_lock(&exclusion);
1871:
1872: if ((*s_etat_processus).var_volatile_requete_arret == -1)
1873: {
1874: deverrouillage_gestionnaire_signaux(s_etat_processus);
1875: pthread_mutex_unlock(&exclusion);
1876: return;
1877: }
1878:
1879: (*s_etat_processus).var_volatile_requete_arret = -1;
1880: (*s_etat_processus).var_volatile_alarme = -1;
1881:
1882: pthread_mutex_unlock(&exclusion);
1883: }
1884: }
1885: else
1886: {
1887: if ((s_thread_principal = recherche_thread_principal(getpid()))
1888: != NULL)
1889: {
1890: envoi_signal_contexte(s_thread_principal, rpl_sigterm);
1891: }
1892: }
1893:
1894: deverrouillage_gestionnaire_signaux(s_etat_processus);
1895: return;
1896: }
1897:
1898: inline static void
1899: signal_int(struct_processus *s_etat_processus, pid_t pid)
1900: {
1901: struct_processus *s_thread_principal;
1902: volatile sig_atomic_t exclusion = 0;
1903:
1904: verrouillage_gestionnaire_signaux(s_etat_processus);
1905:
1906: if (pid == getpid())
1907: {
1908: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1909: {
1910: printf("[%d] RPL/SIGINT (thread %llu)\n", (int) getpid(),
1911: (unsigned long long) pthread_self());
1912: fflush(stdout);
1913: }
1914:
1915: if ((*s_etat_processus).pid_processus_pere != getpid())
1916: {
1917: envoi_signal_processus((*s_etat_processus).pid_processus_pere,
1918: rpl_sigint, d_faux);
1919: }
1920: else
1921: {
1922: (*s_etat_processus).var_volatile_traitement_sigint = -1;
1923:
1924: while(exclusion == 1);
1925: exclusion = 1;
1926:
1927: if ((*s_etat_processus).var_volatile_requete_arret == -1)
1928: {
1929: deverrouillage_gestionnaire_signaux(s_etat_processus);
1930: exclusion = 0;
1931: return;
1932: }
1933:
1934: if ((*s_etat_processus).langue == 'F')
1935: {
1936: printf("+++Interruption\n");
1937: }
1938: else
1939: {
1940: printf("+++Interrupt\n");
1941: }
1942:
1943: fflush(stdout);
1944:
1945: (*s_etat_processus).var_volatile_requete_arret = -1;
1946: (*s_etat_processus).var_volatile_alarme = -1;
1947:
1948: exclusion = 0;
1949: }
1950: }
1951: else
1952: {
1953: if ((s_thread_principal = recherche_thread_principal(getpid()))
1954: != NULL)
1955: {
1956: envoi_signal_contexte(s_thread_principal, rpl_sigint);
1957: }
1958: }
1959:
1960: deverrouillage_gestionnaire_signaux(s_etat_processus);
1961: return;
1962: }
1963:
1964: static inline void
1965: signal_tstp(struct_processus *s_etat_processus, pid_t pid)
1966: {
1967: struct_processus *s_thread_principal;
1968:
1969: verrouillage_gestionnaire_signaux(s_etat_processus);
1970:
1971: if (pid == getpid())
1972: {
1973: /*
1974: * 0 => fonctionnement normal
1975: * -1 => requête
1976: * 1 => requête acceptée en attente de traitement
1977: */
1978:
1979: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1980: {
1981: printf("[%d] RPL/SIGTSTP (thread %llu)\n", (int) getpid(),
1982: (unsigned long long) pthread_self());
1983: fflush(stdout);
1984: }
1985:
1986: if ((*s_etat_processus).var_volatile_processus_pere == 0)
1987: {
1988: envoi_signal_processus((*s_etat_processus).pid_processus_pere,
1989: rpl_sigtstp, d_faux);
1990: }
1991: else
1992: {
1993: (*s_etat_processus).var_volatile_requete_arret2 = -1;
1994: }
1995: }
1996: else
1997: {
1998: // Envoi d'un signal au thread maître du groupe.
1999:
2000: if ((s_thread_principal = recherche_thread_principal(getpid()))
2001: != NULL)
2002: {
2003: envoi_signal_contexte(s_thread_principal, rpl_sigtstp);
2004: }
2005: }
2006:
2007: deverrouillage_gestionnaire_signaux(s_etat_processus);
2008: return;
2009: }
2010:
2011: static void
2012: sortie_interruption_depassement_pile(void *arg1, void *arg2, void *arg3)
2013: {
2014: switch((*((volatile int *) arg1)))
2015: {
2016: case 1:
2017: longjmp(contexte_ecriture, -1);
2018: break;
2019:
2020: case 2:
2021: longjmp(contexte_impression, -1);
2022: break;
2023: }
2024:
2025: return;
2026: }
2027:
2028: void
2029: interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
2030: {
2031: if ((urgence == 0) && (routine_recursive != 0))
2032: {
2033: // On peut tenter de récupérer le dépassement de pile. Si la variable
2034: // 'routine_recursive' est non nulle, on récupère l'erreur.
2035:
2036: sigsegv_leave_handler(sortie_interruption_depassement_pile,
2037: (void *) &routine_recursive, NULL, NULL);
2038: }
2039:
2040: // Ici, la panique est totale et il vaut mieux quitter l'application.
2041: interruption3(SIGUSR2);
2042: return;
2043: }
2044:
2045: int
2046: interruption_violation_access(void *adresse_fautive, int gravite)
2047: {
2048: unsigned char message[] = "+++System : Trying to catch access "
2049: "violation\n";
2050:
2051: static int compteur_erreur = 0;
2052:
2053: if ((gravite == 0) && (routine_recursive != 0))
2054: {
2055: // Il peut s'agir d'un dépassement de pile.
2056:
2057: sigsegv_leave_handler(sortie_interruption_depassement_pile,
2058: (void *) &routine_recursive, NULL, NULL);
2059: }
2060:
2061: // On est dans une bonne vieille violation d'accès. On essaie
2062: // de fermer au mieux l'application.
2063:
2064: compteur_erreur++;
2065:
2066: if (compteur_erreur >= 2)
2067: {
2068: // Erreurs multiples, on arrête l'application.
2069: interruption3(SIGSEGV);
2070: return(0);
2071: }
2072:
2073: # pragma GCC diagnostic push
2074: # pragma GCC diagnostic ignored "-Wunused-result"
2075:
2076: write(STDERR_FILENO, message, strlen(message));
2077:
2078: # pragma GCC diagnostic pop
2079:
2080: if (pid_processus_pere == getpid())
2081: {
2082: longjmp(contexte_initial, -1);
2083: return(1);
2084: }
2085: else
2086: {
2087: longjmp(contexte_processus, -1);
2088: return(1);
2089: }
2090:
2091: // On renvoie 0 parce qu'on décline toute responsabilité quant à la
2092: // suite des événements...
2093: return(0);
2094: }
2095:
2096: // Traitement de rpl_sigstart
2097:
2098: static inline void
2099: signal_start(struct_processus *s_etat_processus, pid_t pid)
2100: {
2101: struct_processus *s_thread_principal;
2102:
2103: verrouillage_gestionnaire_signaux(s_etat_processus);
2104:
2105: if (pid == getpid())
2106: {
2107: (*s_etat_processus).demarrage_fils = d_vrai;
2108: }
2109: else
2110: {
2111: // Envoi d'un signal au thread maître du groupe.
2112:
2113: if ((s_thread_principal = recherche_thread_principal(getpid()))
2114: != NULL)
2115: {
2116: envoi_signal_contexte(s_thread_principal, rpl_sigstart);
2117: }
2118: }
2119:
2120: deverrouillage_gestionnaire_signaux(s_etat_processus);
2121: return;
2122: }
2123:
2124: // Traitement de rpl_sigcont
2125:
2126: static inline void
2127: signal_cont(struct_processus *s_etat_processus, pid_t pid)
2128: {
2129: struct_processus *s_thread_principal;
2130:
2131: verrouillage_gestionnaire_signaux(s_etat_processus);
2132:
2133: if (pid == getpid())
2134: {
2135: (*s_etat_processus).redemarrage_processus = d_vrai;
2136: }
2137: else
2138: {
2139: // Envoi d'un signal au thread maître du groupe.
2140:
2141: if ((s_thread_principal = recherche_thread_principal(getpid()))
2142: != NULL)
2143: {
2144: envoi_signal_contexte(s_thread_principal, rpl_sigcont);
2145: }
2146: }
2147:
2148: deverrouillage_gestionnaire_signaux(s_etat_processus);
2149: return;
2150: }
2151:
2152: // Traitement de rpl_sigstop
2153:
2154: static inline void
2155: signal_stop(struct_processus *s_etat_processus, pid_t pid)
2156: {
2157: struct_processus *s_thread_principal;
2158:
2159: verrouillage_gestionnaire_signaux(s_etat_processus);
2160:
2161: if (pid == getpid())
2162: {
2163: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2164: {
2165: printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
2166: (unsigned long long) pthread_self());
2167: fflush(stdout);
2168: }
2169:
2170: /*
2171: * var_globale_traitement_retarde_stop :
2172: * 0 -> traitement immédiat
2173: * 1 -> traitement retardé (aucun signal reçu)
2174: * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
2175: */
2176:
2177: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
2178: {
2179: (*s_etat_processus).var_volatile_requete_arret = -1;
2180: }
2181: else
2182: {
2183: (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
2184: }
2185: }
2186: else
2187: {
2188: // Envoi d'un signal au thread maître du groupe.
2189:
2190: if ((s_thread_principal = recherche_thread_principal(getpid()))
2191: != NULL)
2192: {
2193: envoi_signal_contexte(s_thread_principal, rpl_sigstop);
2194: }
2195: }
2196:
2197: deverrouillage_gestionnaire_signaux(s_etat_processus);
2198: return;
2199: }
2200:
2201: // Traitement de rpl_siginject
2202:
2203: static inline void
2204: signal_inject(struct_processus *s_etat_processus, pid_t pid)
2205: {
2206: verrouillage_gestionnaire_signaux(s_etat_processus);
2207:
2208: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2209: {
2210: deverrouillage_gestionnaire_signaux(s_etat_processus);
2211: return;
2212: }
2213:
2214: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2215: {
2216: printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
2217: (unsigned long long) pthread_self());
2218: fflush(stdout);
2219: }
2220:
2221: deverrouillage_gestionnaire_signaux(s_etat_processus);
2222: return;
2223: }
2224:
2225:
2226: static inline void
2227: signal_urg(struct_processus *s_etat_processus, pid_t pid)
2228: {
2229: struct_processus *s_thread_principal;
2230:
2231: verrouillage_gestionnaire_signaux(s_etat_processus);
2232:
2233: if (pid == getpid())
2234: {
2235: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2236: {
2237: printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
2238: (unsigned long long) pthread_self());
2239: fflush(stdout);
2240: }
2241:
2242: (*s_etat_processus).var_volatile_alarme = -1;
2243: (*s_etat_processus).var_volatile_requete_arret = -1;
2244: }
2245: else
2246: {
2247: // Envoi d'un signal au thread maître du groupe.
2248:
2249: if ((s_thread_principal = recherche_thread_principal(getpid()))
2250: != NULL)
2251: {
2252: envoi_signal_contexte(s_thread_principal, rpl_sigurg);
2253: }
2254: }
2255:
2256: deverrouillage_gestionnaire_signaux(s_etat_processus);
2257: return;
2258: }
2259:
2260: // Traitement de rpl_sigabort
2261:
2262: static inline void
2263: signal_abort(struct_processus *s_etat_processus, pid_t pid)
2264: {
2265: struct_processus *s_thread_principal;
2266:
2267: verrouillage_gestionnaire_signaux(s_etat_processus);
2268:
2269: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2270: {
2271: deverrouillage_gestionnaire_signaux(s_etat_processus);
2272: return;
2273: }
2274:
2275: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2276: {
2277: printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
2278: (unsigned long long) pthread_self());
2279: fflush(stdout);
2280: }
2281:
2282: if (pid == getpid())
2283: {
2284: (*s_etat_processus).arret_depuis_abort = -1;
2285:
2286: /*
2287: * var_globale_traitement_retarde_stop :
2288: * 0 -> traitement immédiat
2289: * 1 -> traitement retardé (aucun signal reçu)
2290: * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
2291: */
2292:
2293: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
2294: {
2295: (*s_etat_processus).var_volatile_requete_arret = -1;
2296: }
2297: else
2298: {
2299: (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
2300: }
2301: }
2302: else
2303: {
2304: (*s_etat_processus).arret_depuis_abort = -1;
2305:
2306: // Envoi d'un signal au thread maître du groupe.
2307:
2308: if ((s_thread_principal = recherche_thread_principal(getpid()))
2309: != NULL)
2310: {
2311: envoi_signal_contexte(s_thread_principal, rpl_sigabort);
2312: }
2313: }
2314:
2315: deverrouillage_gestionnaire_signaux(s_etat_processus);
2316: return;
2317: }
2318:
2319:
2320: static inline void
2321: signal_hup(struct_processus *s_etat_processus, pid_t pid)
2322: {
2323: file *fichier;
2324:
2325: unsigned char nom[8 + 64 + 1];
2326:
2327: verrouillage_gestionnaire_signaux(s_etat_processus);
2328:
2329: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2330: {
2331: deverrouillage_gestionnaire_signaux(s_etat_processus);
2332: return;
2333: }
2334:
2335: snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
2336: (unsigned long long) getpid(),
2337: (unsigned long long) pthread_self());
2338:
2339: # pragma GCC diagnostic push
2340: # pragma GCC diagnostic ignored "-Wunused-result"
2341:
2342: if ((fichier = fopen(nom, "w+")) != NULL)
2343: {
2344: fclose(fichier);
2345:
2346: freopen(nom, "w", stdout);
2347: freopen(nom, "w", stderr);
2348: }
2349:
2350: freopen("/dev/null", "r", stdin);
2351:
2352: # pragma GCC diagnostic pop
2353:
2354: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2355: {
2356: printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
2357: (unsigned long long) pthread_self());
2358: fflush(stdout);
2359: }
2360:
2361: deverrouillage_gestionnaire_signaux(s_etat_processus);
2362: return;
2363: }
2364:
2365: void
2366: traitement_exceptions_gsl(const char *reason, const char *file,
2367: int line, int gsl_errno)
2368: {
2369: code_erreur_gsl = gsl_errno;
2370: envoi_signal_processus(getpid(), rpl_sigexcept, d_faux);
2371: return;
2372: }
2373:
2374: static inline void
2375: signal_except(struct_processus *s_etat_processus, pid_t pid)
2376: {
2377: verrouillage_gestionnaire_signaux(s_etat_processus);
2378:
2379: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2380: {
2381: deverrouillage_gestionnaire_signaux(s_etat_processus);
2382: return;
2383: }
2384:
2385: (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
2386: deverrouillage_gestionnaire_signaux(s_etat_processus);
2387:
2388: return;
2389: }
2390:
2391: static inline void
2392: envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
2393: pid_t pid_source)
2394: {
2395: switch(signal)
2396: {
2397: case rpl_signull:
2398: break;
2399:
2400: case rpl_sigint:
2401: signal_int(s_etat_processus, pid_source);
2402: break;
2403:
2404: case rpl_sigterm:
2405: signal_term(s_etat_processus, pid_source);
2406: break;
2407:
2408: case rpl_sigstart:
2409: signal_start(s_etat_processus, pid_source);
2410: break;
2411:
2412: case rpl_sigcont:
2413: signal_cont(s_etat_processus, pid_source);
2414: break;
2415:
2416: case rpl_sigstop:
2417: signal_stop(s_etat_processus, pid_source);
2418: break;
2419:
2420: case rpl_sigabort:
2421: signal_abort(s_etat_processus, pid_source);
2422: break;
2423:
2424: case rpl_sigurg:
2425: signal_urg(s_etat_processus, pid_source);
2426: break;
2427:
2428: case rpl_siginject:
2429: signal_inject(s_etat_processus, pid_source);
2430: break;
2431:
2432: case rpl_sigalrm:
2433: signal_alrm(s_etat_processus, pid_source);
2434: break;
2435:
2436: case rpl_sighup:
2437: signal_hup(s_etat_processus, pid_source);
2438: break;
2439:
2440: case rpl_sigtstp:
2441: signal_tstp(s_etat_processus, pid_source);
2442: break;
2443:
2444: case rpl_sigexcept:
2445: signal_except(s_etat_processus, pid_source);
2446: break;
2447:
2448: default:
2449: if ((*s_etat_processus).langue == 'F')
2450: {
2451: printf("+++System : Signal inconnu (%d) !\n", signal);
2452: }
2453: else
2454: {
2455: printf("+++System : Spurious signal (%d) !\n", signal);
2456: }
2457:
2458: break;
2459: }
2460:
2461: return;
2462: }
2463:
2464: void
2465: scrutation_interruptions(struct_processus *s_etat_processus)
2466: {
2467: // Interruptions qui arrivent sur le processus depuis un
2468: // processus externe.
2469:
2470: // Les pointeurs de lecture pointent sur les prochains éléments
2471: // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
2472: // écrire.
2473:
2474: if (sem_trywait(semaphore_queue_signaux) == 0)
2475: {
2476: while((*s_queue_signaux).pointeur_lecture !=
2477: (*s_queue_signaux).pointeur_ecriture)
2478: {
2479: // Il y a un signal en attente dans le segment partagé. On le
2480: // traite.
2481:
2482: envoi_interruptions(s_etat_processus,
2483: (*s_queue_signaux).queue[(*s_queue_signaux)
2484: .pointeur_lecture].signal, (*s_queue_signaux).queue
2485: [(*s_queue_signaux).pointeur_lecture].pid);
2486: (*s_queue_signaux).pointeur_lecture =
2487: ((*s_queue_signaux).pointeur_lecture + 1)
2488: % LONGUEUR_QUEUE_SIGNAUX;
2489:
2490: # ifndef IPCS_SYSV
2491: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
2492: MS_ASYNC | MS_INVALIDATE) != 0)
2493: {
2494: sem_post(semaphore_queue_signaux);
2495: (*s_etat_processus).erreur_systeme = d_es_processus;
2496: return;
2497: }
2498: # endif
2499:
2500: while(sem_wait(semaphore_signalisation) != 0)
2501: {
2502: if (errno != EINTR)
2503: {
2504: (*s_etat_processus).erreur_systeme = d_es_processus;
2505: return;
2506: }
2507: }
2508: }
2509:
2510: sem_post(semaphore_queue_signaux);
2511: }
2512:
2513: // Interruptions qui arrivent depuis le groupe courant de threads.
2514:
2515: if (pthread_mutex_trylock(&mutex_liste_threads) == 0)
2516: {
2517: if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
2518: {
2519: while((*s_etat_processus).pointeur_signal_lecture !=
2520: (*s_etat_processus).pointeur_signal_ecriture)
2521: {
2522: // Il y a un signal dans la queue du thread courant.
2523: // On le traite.
2524:
2525: envoi_interruptions(s_etat_processus,
2526: (*s_etat_processus).signaux_en_queue
2527: [(*s_etat_processus).pointeur_signal_lecture],
2528: getpid());
2529: (*s_etat_processus).pointeur_signal_lecture =
2530: ((*s_etat_processus).pointeur_signal_lecture + 1)
2531: % LONGUEUR_QUEUE_SIGNAUX;
2532:
2533: while(sem_wait(semaphore_signalisation) != 0)
2534: {
2535: if (errno != EINTR)
2536: {
2537: if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
2538: {
2539: (*s_etat_processus).erreur_systeme = d_es_processus;
2540: return;
2541: }
2542:
2543: (*s_etat_processus).erreur_systeme = d_es_processus;
2544: return;
2545: }
2546: }
2547: }
2548:
2549: pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
2550: }
2551:
2552: pthread_mutex_unlock(&mutex_liste_threads);
2553: }
2554:
2555: return;
2556: }
2557:
2558:
2559: /*
2560: ================================================================================
2561: Fonction renvoyant le nom du segment de mémoire partagée en fonction
2562: du pid du processus.
2563: ================================================================================
2564: Entrée : Chemin absolue servant de racine, pid du processus
2565: --------------------------------------------------------------------------------
2566: Sortie : NULL ou nom du segment
2567: --------------------------------------------------------------------------------
2568: Effet de bord : Néant
2569: ================================================================================
2570: */
2571:
2572: static unsigned char *
2573: nom_segment(unsigned char *chemin, pid_t pid)
2574: {
2575: unsigned char *fichier;
2576:
2577: # ifdef IPCS_SYSV // !POSIX
2578: # ifndef OS2 // !OS2
2579:
2580: if ((fichier = sys_malloc((strlen(chemin) + 1 + 256 + 1) *
2581: sizeof(unsigned char))) == NULL)
2582: {
2583: return(NULL);
2584: }
2585:
2586: sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
2587: # else // OS2
2588: if ((fichier = sys_malloc((10 + 256 + 1) * sizeof(unsigned char)))
2589: == NULL)
2590: {
2591: return(NULL);
2592: }
2593:
2594: sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
2595: # endif // OS2
2596: # else // POSIX
2597:
2598: if ((fichier = sys_malloc((1 + 256 + 1) *
2599: sizeof(unsigned char))) == NULL)
2600: {
2601: return(NULL);
2602: }
2603:
2604: sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
2605: # endif
2606:
2607: return(fichier);
2608: }
2609:
2610:
2611: /*
2612: ================================================================================
2613: Fonctions d'envoi d'un signal à un thread ou à un processus.
2614: ================================================================================
2615: Entrée : processus et signal
2616: --------------------------------------------------------------------------------
2617: Sortie : erreur
2618: --------------------------------------------------------------------------------
2619: Effet de bord : Néant
2620: ================================================================================
2621: */
2622:
2623: int
2624: envoi_signal_processus(pid_t pid, enum signaux_rpl signal,
2625: logical1 test_ouverture)
2626: {
2627: # ifndef OS2
2628: int segment;
2629: # endif
2630:
2631: # ifndef IPCS_SYSV
2632: sem_t *semaphore;
2633: sem_t *signalisation;
2634: # else
2635: sem_t *semaphore;
2636: sem_t *signalisation;
2637: # ifndef OS2
2638: int desc;
2639: key_t clef;
2640: # endif
2641: # endif
2642:
2643: struct_queue_signaux *queue;
2644:
2645: struct timespec attente;
2646:
2647: unsigned char *nom;
2648:
2649: // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
2650: // mémoire puis d'y inscrire le signal à traiter.
2651:
2652: if (pid == getpid())
2653: {
2654: // Le signal est envoyé au même processus.
2655:
2656: if (s_queue_signaux == NULL)
2657: {
2658: return(1);
2659: }
2660:
2661: while(sem_wait(semaphore_queue_signaux) != 0)
2662: {
2663: if (errno != EINTR)
2664: {
2665: return(1);
2666: }
2667: }
2668:
2669: (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
2670: .pid = pid;
2671: (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
2672: .signal = signal;
2673:
2674: (*s_queue_signaux).pointeur_ecriture =
2675: ((*s_queue_signaux).pointeur_ecriture + 1)
2676: % LONGUEUR_QUEUE_SIGNAUX;
2677:
2678: # ifndef IPCS_SYSV
2679: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
2680: MS_ASYNC | MS_INVALIDATE) != 0)
2681: {
2682: sem_post(semaphore_queue_signaux);
2683: return(1);
2684: }
2685: # endif
2686:
2687: if (sem_post(semaphore_queue_signaux) != 0)
2688: {
2689: return(1);
2690: }
2691:
2692: if (sem_post(semaphore_signalisation) != 0)
2693: {
2694: return(1);
2695: }
2696: }
2697: else
2698: {
2699: // Le signal est envoyé depuis un processus distinct.
2700:
2701: # ifdef IPCS_SYSV
2702: if ((nom = nom_segment(racine_segment, pid)) == NULL)
2703: {
2704: return(1);
2705: }
2706:
2707: # ifndef OS2 // SysV
2708: if (test_ouverture == d_vrai)
2709: {
2710: attente.tv_sec = 0;
2711: attente.tv_nsec = GRANULARITE_us * 1000;
2712:
2713: while((desc = open(nom, O_RDWR)) == -1)
2714: {
2715: nanosleep(&attente, NULL);
2716: INCR_GRANULARITE(attente.tv_nsec);
2717: }
2718: }
2719: else
2720: {
2721: if ((desc = open(nom, O_RDWR)) == -1)
2722: {
2723: sys_free(nom);
2724: return(1);
2725: }
2726: }
2727:
2728: close(desc);
2729:
2730: if ((clef = ftok(nom, 1)) == -1)
2731: {
2732: sys_free(nom);
2733: return(1);
2734: }
2735:
2736: sys_free(nom);
2737:
2738: if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
2739: == -1)
2740: {
2741: return(1);
2742: }
2743:
2744: queue = shmat(segment, NULL, 0);
2745: # else // OS/2
2746: if (test_ouverture == d_vrai)
2747: {
2748: attente.tv_sec = 0;
2749: attente.tv_nsec = GRANULARITE_us * 1000;
2750:
2751: while(DosGetNamedSharedMem((PVOID) &queue, nom,
2752: PAG_WRITE | PAG_READ) != 0)
2753: {
2754: nanosleep(&attente, NULL);
2755: INCR_GRANULARITE(attente.tv_nsec);
2756: }
2757: }
2758: else
2759: {
2760: if (DosGetNamedSharedMem((PVOID) &queue, nom,
2761: PAG_WRITE | PAG_READ) != 0)
2762: {
2763: sys_free(nom);
2764: return(1);
2765: }
2766: }
2767:
2768: sys_free(nom);
2769: # endif
2770: # else // POSIX
2771: if ((nom = nom_segment(racine_segment, pid)) == NULL)
2772: {
2773: return(1);
2774: }
2775:
2776: if (test_ouverture == d_vrai)
2777: {
2778: attente.tv_sec = 0;
2779: attente.tv_nsec = GRANULARITE_us * 1000;
2780:
2781: while((segment = shm_open(nom, O_RDWR, 0)) == -1)
2782: {
2783: nanosleep(&attente, NULL);
2784: INCR_GRANULARITE(attente.tv_nsec);
2785: }
2786: }
2787: else
2788: {
2789: if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
2790: {
2791: sys_free(nom);
2792: return(1);
2793: }
2794: }
2795:
2796: sys_free(nom);
2797:
2798: if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
2799: PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
2800: MAP_FAILED)
2801: {
2802: close(segment);
2803: return(1);
2804: }
2805: # endif
2806:
2807: // À ce moment, le segment de mémoire partagée est projeté
2808: // dans l'espace du processus.
2809:
2810: if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
2811: {
2812: # ifndef IPCS_SYSV // POSIX
2813: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2814: {
2815: munmap(queue, sizeof(struct_queue_signaux));
2816: close(segment);
2817: return(1);
2818: }
2819:
2820: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2821: {
2822: close(segment);
2823: return(1);
2824: }
2825:
2826: close(segment);
2827: # else // IPCS_SYSV
2828: # ifndef OS2 // SysV
2829: if (shmdt(queue) != 0)
2830: {
2831: return(1);
2832: }
2833: # else // OS/2
2834: // Pendant de DosGetNamedSHaredMem()
2835: # endif
2836: # endif
2837: return(1);
2838: }
2839:
2840: if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
2841: == SEM_FAILED)
2842: {
2843: # ifndef IPCS_SYSV // POSIX
2844: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2845: {
2846: munmap(queue, sizeof(struct_queue_signaux));
2847: close(segment);
2848: sem_close(semaphore);
2849: return(1);
2850: }
2851:
2852: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2853: {
2854: close(segment);
2855: sem_close(semaphore);
2856: return(1);
2857: }
2858:
2859: close(segment);
2860: # else // IPCS_SYSV
2861: # ifndef OS2 // SysV
2862: if (shmdt(queue) != 0)
2863: {
2864: sem_close(semaphore);
2865: return(1);
2866: }
2867: # else // OS/2
2868: // Pendant de DosGetNamedSHaredMem()
2869: # endif
2870: # endif
2871:
2872: sem_close(semaphore);
2873: return(1);
2874: }
2875:
2876: while(sem_wait(semaphore) != 0)
2877: {
2878: if (errno != EINTR)
2879: {
2880: # ifndef IPCS_SYSV // POSIX
2881: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE)
2882: != 0)
2883: {
2884: munmap(queue, sizeof(struct_queue_signaux));
2885: sem_close(semaphore);
2886: sem_close(signalisation);
2887: close(segment);
2888: return(1);
2889: }
2890:
2891: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2892: {
2893: sem_close(semaphore);
2894: sem_close(signalisation);
2895: close(segment);
2896: return(1);
2897: }
2898:
2899: close(segment);
2900: # else // IPCS_SYSV
2901: # ifndef OS2 // SysV
2902: if (shmdt(queue) != 0)
2903: {
2904: sem_close(semaphore);
2905: sem_close(signalisation);
2906: return(1);
2907: }
2908: # else // OS/2
2909: // Pendant de DosGetNamedSHaredMem()
2910: # endif
2911: # endif
2912:
2913: sem_close(semaphore);
2914: sem_close(signalisation);
2915: return(1);
2916: }
2917: }
2918:
2919: (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
2920: (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
2921:
2922: (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
2923: % LONGUEUR_QUEUE_SIGNAUX;
2924:
2925: if (sem_post(semaphore) != 0)
2926: {
2927: # ifndef IPCS_SYSV // POSIX
2928: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2929: {
2930: munmap(queue, sizeof(struct_queue_signaux));
2931: close(segment);
2932: sem_close(semaphore);
2933: sem_close(signalisation);
2934: return(1);
2935: }
2936:
2937: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2938: {
2939: close(segment);
2940: sem_close(semaphore);
2941: sem_close(signalisation);
2942: return(1);
2943: }
2944:
2945: close(segment);
2946: # else // IPCS_SYSV
2947: # ifndef OS2 // SysV
2948: if (shmdt(queue) != 0)
2949: {
2950: sem_close(semaphore);
2951: sem_close(signalisation);
2952: return(1);
2953: }
2954: # else // OS/2
2955: // Pendant de DosGetNamedSHaredMem()
2956: # endif
2957: # endif
2958:
2959: sem_close(semaphore);
2960: sem_close(signalisation);
2961: return(1);
2962: }
2963:
2964: if (sem_close(semaphore) != 0)
2965: {
2966: # ifndef IPCS_SYSV // POSIX
2967: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2968: {
2969: munmap(queue, sizeof(struct_queue_signaux));
2970: close(segment);
2971: sem_close(signalisation);
2972: return(1);
2973: }
2974:
2975: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2976: {
2977: close(segment);
2978: sem_close(signalisation);
2979: return(1);
2980: }
2981:
2982: close(segment);
2983: # else // IPCS_SYSV
2984: # ifndef OS2 // SysV
2985: if (shmdt(queue) != 0)
2986: {
2987: sem_close(signalisation);
2988: return(1);
2989: }
2990: # else // OS/2
2991: // Pendant de DosGetNamedSHaredMem()
2992: # endif
2993: # endif
2994:
2995: sem_close(signalisation);
2996: return(1);
2997: }
2998:
2999: if (sem_post(signalisation) != 0)
3000: {
3001: # ifndef IPCS_SYSV // POSIX
3002: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3003: {
3004: munmap(queue, sizeof(struct_queue_signaux));
3005: close(segment);
3006: sem_close(signalisation);
3007: return(1);
3008: }
3009:
3010: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3011: {
3012: close(segment);
3013: sem_close(signalisation);
3014: return(1);
3015: }
3016:
3017: close(segment);
3018: # else // IPCS_SYSV
3019: # ifndef OS2 // SysV
3020: if (shmdt(queue) != 0)
3021: {
3022: sem_close(signalisation);
3023: return(1);
3024: }
3025: # else // OS/2
3026: // Pendant de DosGetNamedSHaredMem()
3027: # endif
3028: # endif
3029:
3030: sem_close(signalisation);
3031: return(1);
3032: }
3033:
3034: if (sem_close(signalisation) != 0)
3035: {
3036: # ifndef IPCS_SYSV // POSIX
3037: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3038: {
3039: munmap(queue, sizeof(struct_queue_signaux));
3040: close(segment);
3041: return(1);
3042: }
3043:
3044: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3045: {
3046: close(segment);
3047: return(1);
3048: }
3049:
3050: close(segment);
3051: # else // IPCS_SYSV
3052: # ifndef OS2 // SysV
3053: if (shmdt(queue) != 0)
3054: {
3055: return(1);
3056: }
3057: # else // OS/2
3058: // Pendant de DosGetNamedSHaredMem()
3059: # endif
3060: # endif
3061:
3062: return(1);
3063: }
3064:
3065: # ifndef IPCS_SYSV // POSIX
3066: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3067: {
3068: munmap(queue, sizeof(struct_queue_signaux));
3069: close(segment);
3070: return(1);
3071: }
3072:
3073: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3074: {
3075: close(segment);
3076: return(1);
3077: }
3078:
3079: close(segment);
3080: # else // IPCS_SYSV
3081: # ifndef OS2 // SysV
3082: if (shmdt(queue) != 0)
3083: {
3084: return(1);
3085: }
3086: # else // OS/2
3087: // Pendant de DosGetNamedSHaredMem()
3088: # endif
3089: # endif
3090: }
3091:
3092: return(0);
3093: }
3094:
3095: int
3096: envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
3097: {
3098: // Un signal est envoyé d'un thread à un autre thread du même processus.
3099:
3100: volatile struct_liste_chainee_volatile *l_element_courant;
3101:
3102: struct_processus *s_etat_processus;
3103:
3104: if (pthread_mutex_lock(&mutex_liste_threads) != 0)
3105: {
3106: return(1);
3107: }
3108:
3109: l_element_courant = liste_threads;
3110:
3111: while(l_element_courant != NULL)
3112: {
3113: if (((*((struct_thread *) (*l_element_courant).donnee)).pid
3114: == getpid()) && (pthread_equal((*((struct_thread *)
3115: (*l_element_courant).donnee)).tid, tid) != 0))
3116: {
3117: break;
3118: }
3119:
3120: l_element_courant = (*l_element_courant).suivant;
3121: }
3122:
3123: if (l_element_courant == NULL)
3124: {
3125: pthread_mutex_unlock(&mutex_liste_threads);
3126: return(1);
3127: }
3128:
3129: s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
3130: .s_etat_processus;
3131:
3132: if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
3133: {
3134: pthread_mutex_unlock(&mutex_liste_threads);
3135: return(1);
3136: }
3137:
3138: (*s_etat_processus).signaux_en_queue
3139: [(*s_etat_processus).pointeur_signal_ecriture] = signal;
3140: (*s_etat_processus).pointeur_signal_ecriture =
3141: ((*s_etat_processus).pointeur_signal_ecriture + 1)
3142: % LONGUEUR_QUEUE_SIGNAUX;
3143:
3144: if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
3145: {
3146: pthread_mutex_unlock(&mutex_liste_threads);
3147: return(1);
3148: }
3149:
3150: if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
3151: {
3152: return(1);
3153: }
3154:
3155: if (sem_post(semaphore_signalisation) != 0)
3156: {
3157: return(1);
3158: }
3159:
3160: return(0);
3161: }
3162:
3163: int
3164: envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
3165: enum signaux_rpl signal)
3166: {
3167: pthread_mutex_lock(&((*s_etat_processus_a_signaler).mutex_signaux));
3168: (*s_etat_processus_a_signaler).signaux_en_queue
3169: [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =
3170: signal;
3171: (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
3172: ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
3173: % LONGUEUR_QUEUE_SIGNAUX;
3174: pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
3175:
3176: if (sem_post(semaphore_signalisation) != 0)
3177: {
3178: return(1);
3179: }
3180:
3181: return(0);
3182: }
3183:
3184:
3185: /*
3186: ================================================================================
3187: Fonction créant un segment de mémoire partagée destiné à contenir
3188: la queue des signaux.
3189: ================================================================================
3190: Entrée : structure de description du processus
3191: --------------------------------------------------------------------------------
3192: Sortie : Néant
3193: --------------------------------------------------------------------------------
3194: Effet de bord : Néant
3195: ================================================================================
3196: */
3197:
3198: void
3199: creation_queue_signaux(struct_processus *s_etat_processus)
3200: {
3201: pthread_attr_t attributs;
3202:
3203: unsigned char *nom;
3204:
3205: racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
3206:
3207: # ifndef IPCS_SYSV // POSIX
3208: if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
3209: getpid())) == NULL)
3210: {
3211: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3212: return;
3213: }
3214:
3215: if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
3216: S_IRUSR | S_IWUSR)) == -1)
3217: {
3218: if (errno != EEXIST)
3219: {
3220: sys_free(nom);
3221: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3222: return;
3223: }
3224:
3225: if ((*s_etat_processus).langue == 'F')
3226: {
3227: printf("+++Attention : Le segment de mémoire %s préexiste !\n",
3228: nom);
3229: }
3230: else
3231: {
3232: printf("+++Warning: %s memory segment preexists!\n", nom);
3233: }
3234:
3235: if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_TRUNC,
3236: S_IRUSR | S_IWUSR)) == -1)
3237: {
3238: sys_free(nom);
3239: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3240: return;
3241: }
3242: }
3243:
3244: if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
3245: {
3246: sys_free(nom);
3247: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3248: return;
3249: }
3250:
3251: s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
3252: PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
3253:
3254: if (((void *) s_queue_signaux) == ((void *) -1))
3255: {
3256: if (shm_unlink(nom) == -1)
3257: {
3258: sys_free(nom);
3259: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3260: return;
3261: }
3262:
3263: sys_free(nom);
3264: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3265: return;
3266: }
3267:
3268: sys_free(nom);
3269:
3270: if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
3271: == SEM_FAILED)
3272: {
3273: (*s_etat_processus).erreur_systeme = d_es_processus;
3274: return;
3275: }
3276:
3277: if ((semaphore_signalisation = sem_init2(0, getpid(),
3278: SEM_SIGNALISATION)) == SEM_FAILED)
3279: {
3280: (*s_etat_processus).erreur_systeme = d_es_processus;
3281: return;
3282: }
3283:
3284: if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
3285: SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
3286: {
3287: (*s_etat_processus).erreur_systeme = d_es_processus;
3288: return;
3289: }
3290:
3291: (*s_queue_signaux).pointeur_lecture = 0;
3292: (*s_queue_signaux).pointeur_ecriture = 0;
3293:
3294: (*s_queue_signaux).requete_arret = d_faux;
3295:
3296: if (msync(s_queue_signaux, sizeof(struct_queue_signaux),
3297: MS_ASYNC | MS_INVALIDATE) != 0)
3298: {
3299: (*s_etat_processus).erreur_systeme = d_es_processus;
3300: return;
3301: }
3302: # else // IPCS_SYSV
3303: # ifndef OS2
3304: int segment;
3305: int support;
3306:
3307: key_t clef;
3308:
3309: // Création d'un segment de données associé au PID du processus
3310: // courant
3311:
3312: if ((nom = nom_segment((*s_etat_processus)
3313: .chemin_fichiers_temporaires, getpid())) == NULL)
3314: {
3315: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3316: return;
3317: }
3318:
3319: if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
3320: S_IRUSR | S_IWUSR)) == -1)
3321: {
3322: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
3323: return;
3324: }
3325:
3326: if ((clef = ftok(nom, 1)) == -1)
3327: {
3328: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3329: return;
3330: }
3331:
3332: close(support);
3333: sys_free(nom);
3334:
3335: if ((segment = shmget(clef, sizeof(struct_queue_signaux),
3336: IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
3337: {
3338: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3339: return;
3340: }
3341:
3342: s_queue_signaux = shmat(segment, NULL, 0);
3343: f_queue_signaux = segment;
3344:
3345: if (((void *) s_queue_signaux) == ((void *) -1))
3346: {
3347: if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
3348: {
3349: (*s_etat_processus).erreur_systeme =
3350: d_es_allocation_memoire;
3351: return;
3352: }
3353:
3354: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3355: return;
3356: }
3357:
3358: if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
3359: == SEM_FAILED)
3360: {
3361: (*s_etat_processus).erreur_systeme = d_es_processus;
3362: return;
3363: }
3364:
3365: if ((semaphore_signalisation = sem_init2(0, getpid(),
3366: SEM_SIGNALISATION)) == SEM_FAILED)
3367: {
3368: (*s_etat_processus).erreur_systeme = d_es_processus;
3369: return;
3370: }
3371:
3372: if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
3373: SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
3374: {
3375: (*s_etat_processus).erreur_systeme = d_es_processus;
3376: return;
3377: }
3378:
3379: (*s_queue_signaux).pointeur_lecture = 0;
3380: (*s_queue_signaux).pointeur_ecriture = 0;
3381: (*s_queue_signaux).requete_arret = d_faux;
3382: # else // OS/2
3383: if ((nom = nom_segment(NULL, getpid())) == NULL)
3384: {
3385: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3386: return;
3387: }
3388:
3389: if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
3390: sizeof(struct_queue_signaux),
3391: PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
3392: {
3393: sys_free(nom);
3394: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3395: return;
3396: }
3397:
3398: sys_free(nom);
3399:
3400: sem_init(&((*s_queue_signaux).semaphore), 1, 1);
3401: sem_init(&((*s_queue_signaux).signalisation), 1, 0);
3402: sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
3403:
3404: (*s_queue_signaux).pointeur_lecture = 0;
3405: (*s_queue_signaux).pointeur_ecriture = 0;
3406: (*s_queue_signaux).requete_arret = d_faux;
3407: # endif
3408: # endif
3409:
3410: // Lancement du thread de récupération des signaux.
3411:
3412: if (pthread_attr_init(&attributs) != 0)
3413: {
3414: (*s_etat_processus).erreur_systeme = d_es_processus;
3415: return;
3416: }
3417:
3418: if (pthread_attr_setdetachstate(&attributs,
3419: PTHREAD_CREATE_JOINABLE) != 0)
3420: {
3421: (*s_etat_processus).erreur_systeme = d_es_processus;
3422: return;
3423: }
3424:
3425: if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
3426: thread_surveillance_signaux, s_etat_processus) != 0)
3427: {
3428: (*s_etat_processus).erreur_systeme = d_es_processus;
3429: return;
3430: }
3431:
3432: if (pthread_attr_destroy(&attributs) != 0)
3433: {
3434: (*s_etat_processus).erreur_systeme = d_es_processus;
3435: return;
3436: }
3437:
3438: (*s_queue_signaux).controle = getpid();
3439:
3440: # ifndef IPCS_SYSV
3441: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
3442: MS_ASYNC | MS_INVALIDATE) != 0)
3443: {
3444: (*s_etat_processus).erreur_systeme = d_es_processus;
3445: return;
3446: }
3447: # endif
3448:
3449: if (lancement_thread_signaux(s_etat_processus) == d_erreur)
3450: {
3451: (*s_etat_processus).erreur_systeme = d_es_processus;
3452: return;
3453: }
3454:
3455: return;
3456: }
3457:
3458:
3459: /*
3460: ================================================================================
3461: Fonction libérant le segment de mémoire partagée destiné à contenir
3462: la queue des signaux.
3463: ================================================================================
3464: Entrée : structure de description du processus
3465: --------------------------------------------------------------------------------
3466: Sortie : Néant
3467: --------------------------------------------------------------------------------
3468: Effet de bord : Néant
3469: ================================================================================
3470: */
3471:
3472: void
3473: liberation_queue_signaux(struct_processus *s_etat_processus)
3474: {
3475: # ifdef IPCS_SYSV // SystemV
3476: # ifndef OS2
3477: if (shmdt(s_queue_signaux) == -1)
3478: {
3479: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3480: return;
3481: }
3482: # else // OS/2
3483: # endif
3484: # else // POSIX
3485: sem_close(semaphore_queue_signaux);
3486: sem_close(semaphore_signalisation);
3487: sem_close(semaphore_arret_signalisation);
3488:
3489: if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
3490: {
3491: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3492: return;
3493: }
3494:
3495: close(f_queue_signaux);
3496: # endif
3497:
3498: return;
3499: }
3500:
3501:
3502: /*
3503: ================================================================================
3504: Fonction détruisant le segment de mémoire partagée destiné à contenir
3505: la queue des signaux.
3506: ================================================================================
3507: Entrée : structure de description du processus
3508: --------------------------------------------------------------------------------
3509: Sortie : Néant
3510: --------------------------------------------------------------------------------
3511: Effet de bord : Néant
3512: ================================================================================
3513: */
3514:
3515: void
3516: destruction_queue_signaux(struct_processus *s_etat_processus)
3517: {
3518: # ifndef OS2
3519: unsigned char *nom;
3520: # endif
3521:
3522: sem_wait(semaphore_arret_signalisation);
3523: (*s_queue_signaux).requete_arret = d_vrai;
3524:
3525: # ifndef IPCS_SYSV
3526: msync(s_queue_signaux, sizeof(s_queue_signaux), MS_ASYNC | MS_INVALIDATE);
3527: # endif
3528:
3529: sem_post(semaphore_arret_signalisation);
3530:
3531: // Incrémenter le sémaphore pour être sûr de le débloquer.
3532:
3533: sem_post(semaphore_signalisation);
3534: pthread_join((*s_queue_signaux).thread_signaux, NULL);
3535: arret_thread_signaux(s_etat_processus);
3536:
3537: # ifdef IPCS_SYSV // SystemV
3538: # ifndef OS2
3539: // Il faut commencer par éliminer le sémaphore.
3540:
3541: if (semctl((*semaphore_queue_signaux).sem, 0, IPC_RMID) == -1)
3542: {
3543: (*s_etat_processus).erreur_systeme = d_es_processus;
3544: return;
3545: }
3546:
3547: unlink((*semaphore_queue_signaux).path);
3548: sys_free((*semaphore_queue_signaux).path);
3549:
3550: if (semctl((*semaphore_signalisation).sem, 0, IPC_RMID) == -1)
3551: {
3552: (*s_etat_processus).erreur_systeme = d_es_processus;
3553: return;
3554: }
3555:
3556: unlink((*semaphore_signalisation).path);
3557: sys_free((*semaphore_signalisation).path);
3558:
3559: if (semctl((*semaphore_arret_signalisation).sem, 0, IPC_RMID) == -1)
3560: {
3561: (*s_etat_processus).erreur_systeme = d_es_processus;
3562: return;
3563: }
3564:
3565: unlink((*semaphore_arret_signalisation).path);
3566: sys_free((*semaphore_arret_signalisation).path);
3567:
3568: if (shmdt(s_queue_signaux) == -1)
3569: {
3570: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3571: return;
3572: }
3573:
3574: if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
3575: {
3576: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3577: return;
3578: }
3579:
3580: if ((nom = nom_segment((*s_etat_processus)
3581: .chemin_fichiers_temporaires, getpid())) == NULL)
3582: {
3583: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3584: return;
3585: }
3586:
3587: unlink(nom);
3588: sys_free(nom);
3589: # else
3590: sem_close(&((*s_queue_signaux).semaphore));
3591: sem_destroy(&((*s_queue_signaux).semaphore));
3592:
3593: sem_close(&((*s_queue_signaux).signalisation));
3594: sem_destroy(&((*s_queue_signaux).signalisation));
3595:
3596: sem_close(&((*s_queue_signaux).arret_signalisation));
3597: sem_destroy(&((*s_queue_signaux).arret_signalisation));
3598:
3599: if (DosFreeMem(s_queue_signaux) != 0)
3600: {
3601: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3602: return;
3603: }
3604: # endif
3605: # else // POSIX
3606: sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
3607: sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
3608: sem_destroy2(semaphore_arret_signalisation, getpid(),
3609: SEM_ARRET_SIGNALISATION);
3610:
3611: if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
3612: {
3613: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3614: return;
3615: }
3616:
3617: if ((nom = nom_segment(NULL, getpid())) == NULL)
3618: {
3619: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3620: return;
3621: }
3622:
3623: close(f_queue_signaux);
3624:
3625: if (shm_unlink(nom) != 0)
3626: {
3627: sys_free(nom);
3628: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3629: return;
3630: }
3631:
3632: sys_free(nom);
3633: # endif
3634:
3635: return;
3636: }
3637:
3638: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>