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