1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.25
4: Copyright (C) 1989-2016 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: Procédures de gestion par thread des variables issues des gestionnaires
29: de signaux
30: ================================================================================
31: Entrée : variable globale
32: --------------------------------------------------------------------------------
33: Sortie : variable globale modifiée
34: --------------------------------------------------------------------------------
35: Effets de bord : néant
36: ================================================================================
37: */
38:
39: typedef struct thread
40: {
41: pid_t pid;
42: pthread_t tid;
43:
44: logical1 thread_principal;
45:
46: struct_processus *s_etat_processus;
47: } struct_thread;
48:
49: typedef struct liste_chainee_volatile
50: {
51: volatile struct liste_chainee_volatile *suivant;
52: volatile void *donnee;
53: } struct_liste_chainee_volatile;
54:
55: static volatile struct_liste_chainee_volatile *liste_threads
56: = NULL;
57: static volatile struct_liste_chainee_volatile *liste_threads_surveillance
58: = NULL;
59: static volatile int code_erreur_gsl = 0;
60:
61: unsigned char *racine_segment;
62:
63: static void *
64: thread_surveillance_signaux(void *argument)
65: {
66: // Cette fonction est lancée dans un thread créé par processus pour
67: // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du
68: // signal SIGALRM. Les processus externes n'envoient plus un signal au
69: // processus ou au thread à signaler mais positionnent les informations
70: // nécessaires dans la queue des signaux et incrémentent le sémaphore.
71: // Le sémaphore est décrémenté lorsque le signal est effectivement traité.
72:
73: int ios;
74: int nombre_signaux_envoyes;
75:
76: struct_processus *s_etat_processus;
77:
78: struct timespec attente;
79:
80: volatile struct_liste_chainee_volatile *l_element_courant;
81:
82: sigset_t set;
83:
84: sigfillset(&set);
85: pthread_sigmask(SIG_BLOCK, &set, NULL);
86:
87: s_etat_processus = (struct_processus *) argument;
88:
89: for(;;)
90: {
91: attente.tv_sec = 0;
92: attente.tv_nsec = GRANULARITE_us * 1000;
93:
94: if (sem_wait(semaphore_signalisation) == 0)
95: {
96: 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(), SIGALRM);
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, SIGALRM);
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 SIGALRM 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: // SIGALRM
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: void
2032: interruption_depassement_pile(int urgence, stackoverflow_context_t scp)
2033: {
2034: if ((urgence == 0) && (routine_recursive != 0))
2035: {
2036: // On peut tenter de récupérer le dépassement de pile. Si la variable
2037: // 'routine_recursive' est non nulle, on récupère l'erreur.
2038:
2039: sigsegv_leave_handler(sortie_interruption_depassement_pile,
2040: (void *) &routine_recursive, NULL, NULL);
2041: }
2042:
2043: // Ici, la panique est totale et il vaut mieux quitter l'application.
2044: interruption3(SIGUSR2);
2045: return;
2046: }
2047:
2048: int
2049: interruption_violation_access(void *adresse_fautive, int gravite)
2050: {
2051: unsigned char message[] = "+++System : Trying to catch access "
2052: "violation\n";
2053:
2054: static int compteur_erreur = 0;
2055:
2056: if ((gravite == 0) && (routine_recursive != 0))
2057: {
2058: // Il peut s'agir d'un dépassement de pile.
2059:
2060: sigsegv_leave_handler(sortie_interruption_depassement_pile,
2061: (void *) &routine_recursive, NULL, NULL);
2062: }
2063:
2064: // On est dans une bonne vieille violation d'accès. On essaie
2065: // de fermer au mieux l'application.
2066:
2067: compteur_erreur++;
2068:
2069: if (compteur_erreur >= 2)
2070: {
2071: // Erreurs multiples, on arrête l'application.
2072: interruption3(SIGSEGV);
2073: return(0);
2074: }
2075:
2076: # pragma GCC diagnostic push
2077: # pragma GCC diagnostic ignored "-Wunused-result"
2078:
2079: write(STDERR_FILENO, message, strlen(message));
2080:
2081: # pragma GCC diagnostic pop
2082:
2083: if (pid_processus_pere == getpid())
2084: {
2085: longjmp(contexte_initial, -1);
2086: return(1);
2087: }
2088: else
2089: {
2090: longjmp(contexte_processus, -1);
2091: return(1);
2092: }
2093:
2094: // On renvoie 0 parce qu'on décline toute responsabilité quant à la
2095: // suite des événements...
2096: return(0);
2097: }
2098:
2099: // Traitement de rpl_sigstart
2100:
2101: static inline void
2102: signal_start(struct_processus *s_etat_processus, pid_t pid)
2103: {
2104: struct_processus *s_thread_principal;
2105:
2106: verrouillage_gestionnaire_signaux(s_etat_processus);
2107:
2108: if (pid == getpid())
2109: {
2110: (*s_etat_processus).demarrage_fils = d_vrai;
2111: }
2112: else
2113: {
2114: // Envoi d'un signal au thread maître du groupe.
2115:
2116: if ((s_thread_principal = recherche_thread_principal(getpid()))
2117: != NULL)
2118: {
2119: envoi_signal_contexte(s_thread_principal, rpl_sigstart);
2120: }
2121: }
2122:
2123: deverrouillage_gestionnaire_signaux(s_etat_processus);
2124: return;
2125: }
2126:
2127: // Traitement de rpl_sigcont
2128:
2129: static inline void
2130: signal_cont(struct_processus *s_etat_processus, pid_t pid)
2131: {
2132: struct_processus *s_thread_principal;
2133:
2134: verrouillage_gestionnaire_signaux(s_etat_processus);
2135:
2136: if (pid == getpid())
2137: {
2138: (*s_etat_processus).redemarrage_processus = d_vrai;
2139: }
2140: else
2141: {
2142: // Envoi d'un signal au thread maître du groupe.
2143:
2144: if ((s_thread_principal = recherche_thread_principal(getpid()))
2145: != NULL)
2146: {
2147: envoi_signal_contexte(s_thread_principal, rpl_sigcont);
2148: }
2149: }
2150:
2151: deverrouillage_gestionnaire_signaux(s_etat_processus);
2152: return;
2153: }
2154:
2155: // Traitement de rpl_sigstop
2156:
2157: static inline void
2158: signal_stop(struct_processus *s_etat_processus, pid_t pid)
2159: {
2160: struct_processus *s_thread_principal;
2161:
2162: verrouillage_gestionnaire_signaux(s_etat_processus);
2163:
2164: if (pid == getpid())
2165: {
2166: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2167: {
2168: printf("[%d] RPL/SIGSTOP (thread %llu)\n", (int) getpid(),
2169: (unsigned long long) pthread_self());
2170: fflush(stdout);
2171: }
2172:
2173: /*
2174: * var_globale_traitement_retarde_stop :
2175: * 0 -> traitement immédiat
2176: * 1 -> traitement retardé (aucun signal reçu)
2177: * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
2178: */
2179:
2180: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
2181: {
2182: (*s_etat_processus).var_volatile_requete_arret = -1;
2183: }
2184: else
2185: {
2186: (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
2187: }
2188: }
2189: else
2190: {
2191: // Envoi d'un signal au thread maître du groupe.
2192:
2193: if ((s_thread_principal = recherche_thread_principal(getpid()))
2194: != NULL)
2195: {
2196: envoi_signal_contexte(s_thread_principal, rpl_sigstop);
2197: }
2198: }
2199:
2200: deverrouillage_gestionnaire_signaux(s_etat_processus);
2201: return;
2202: }
2203:
2204: // Traitement de rpl_siginject
2205:
2206: static inline void
2207: signal_inject(struct_processus *s_etat_processus, pid_t pid)
2208: {
2209: verrouillage_gestionnaire_signaux(s_etat_processus);
2210:
2211: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2212: {
2213: deverrouillage_gestionnaire_signaux(s_etat_processus);
2214: return;
2215: }
2216:
2217: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2218: {
2219: printf("[%d] RPL/SIGINJECT (thread %llu)\n", (int) getpid(),
2220: (unsigned long long) pthread_self());
2221: fflush(stdout);
2222: }
2223:
2224: deverrouillage_gestionnaire_signaux(s_etat_processus);
2225: return;
2226: }
2227:
2228:
2229: static inline void
2230: signal_urg(struct_processus *s_etat_processus, pid_t pid)
2231: {
2232: struct_processus *s_thread_principal;
2233:
2234: verrouillage_gestionnaire_signaux(s_etat_processus);
2235:
2236: if (pid == getpid())
2237: {
2238: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2239: {
2240: printf("[%d] RPL/SIGURG (thread %llu)\n", (int) getpid(),
2241: (unsigned long long) pthread_self());
2242: fflush(stdout);
2243: }
2244:
2245: (*s_etat_processus).var_volatile_alarme = -1;
2246: (*s_etat_processus).var_volatile_requete_arret = -1;
2247: }
2248: else
2249: {
2250: // Envoi d'un signal au thread maître du groupe.
2251:
2252: if ((s_thread_principal = recherche_thread_principal(getpid()))
2253: != NULL)
2254: {
2255: envoi_signal_contexte(s_thread_principal, rpl_sigurg);
2256: }
2257: }
2258:
2259: deverrouillage_gestionnaire_signaux(s_etat_processus);
2260: return;
2261: }
2262:
2263: // Traitement de rpl_sigabort
2264:
2265: static inline void
2266: signal_abort(struct_processus *s_etat_processus, pid_t pid)
2267: {
2268: struct_processus *s_thread_principal;
2269:
2270: verrouillage_gestionnaire_signaux(s_etat_processus);
2271:
2272: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2273: {
2274: deverrouillage_gestionnaire_signaux(s_etat_processus);
2275: return;
2276: }
2277:
2278: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2279: {
2280: printf("[%d] RPL/SIGABORT (thread %llu)\n", (int) getpid(),
2281: (unsigned long long) pthread_self());
2282: fflush(stdout);
2283: }
2284:
2285: if (pid == getpid())
2286: {
2287: (*s_etat_processus).arret_depuis_abort = -1;
2288:
2289: /*
2290: * var_globale_traitement_retarde_stop :
2291: * 0 -> traitement immédiat
2292: * 1 -> traitement retardé (aucun signal reçu)
2293: * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
2294: */
2295:
2296: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
2297: {
2298: (*s_etat_processus).var_volatile_requete_arret = -1;
2299: }
2300: else
2301: {
2302: (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
2303: }
2304: }
2305: else
2306: {
2307: (*s_etat_processus).arret_depuis_abort = -1;
2308:
2309: // Envoi d'un signal au thread maître du groupe.
2310:
2311: if ((s_thread_principal = recherche_thread_principal(getpid()))
2312: != NULL)
2313: {
2314: envoi_signal_contexte(s_thread_principal, rpl_sigabort);
2315: }
2316: }
2317:
2318: deverrouillage_gestionnaire_signaux(s_etat_processus);
2319: return;
2320: }
2321:
2322:
2323: static inline void
2324: signal_hup(struct_processus *s_etat_processus, pid_t pid)
2325: {
2326: file *fichier;
2327:
2328: unsigned char nom[8 + 64 + 1];
2329:
2330: verrouillage_gestionnaire_signaux(s_etat_processus);
2331:
2332: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2333: {
2334: deverrouillage_gestionnaire_signaux(s_etat_processus);
2335: return;
2336: }
2337:
2338: snprintf(nom, 8 + 64 + 1, "rpl-out-%llu-%llu",
2339: (unsigned long long) getpid(),
2340: (unsigned long long) pthread_self());
2341:
2342: # pragma GCC diagnostic push
2343: # pragma GCC diagnostic ignored "-Wunused-result"
2344:
2345: if ((fichier = fopen(nom, "w+")) != NULL)
2346: {
2347: fclose(fichier);
2348:
2349: freopen(nom, "w", stdout);
2350: freopen(nom, "w", stderr);
2351: }
2352:
2353: freopen("/dev/null", "r", stdin);
2354:
2355: # pragma GCC diagnostic pop
2356:
2357: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2358: {
2359: printf("[%d] RPL/SIGHUP (thread %llu)\n", (int) getpid(),
2360: (unsigned long long) pthread_self());
2361: fflush(stdout);
2362: }
2363:
2364: deverrouillage_gestionnaire_signaux(s_etat_processus);
2365: return;
2366: }
2367:
2368: void
2369: traitement_exceptions_gsl(const char *reason, const char *file,
2370: int line, int gsl_errno)
2371: {
2372: code_erreur_gsl = gsl_errno;
2373: envoi_signal_processus(getpid(), rpl_sigexcept, d_faux);
2374: return;
2375: }
2376:
2377: static inline void
2378: signal_except(struct_processus *s_etat_processus, pid_t pid)
2379: {
2380: verrouillage_gestionnaire_signaux(s_etat_processus);
2381:
2382: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2383: {
2384: deverrouillage_gestionnaire_signaux(s_etat_processus);
2385: return;
2386: }
2387:
2388: (*s_etat_processus).var_volatile_exception_gsl = code_erreur_gsl;
2389: deverrouillage_gestionnaire_signaux(s_etat_processus);
2390:
2391: return;
2392: }
2393:
2394: static inline void
2395: envoi_interruptions(struct_processus *s_etat_processus, enum signaux_rpl signal,
2396: pid_t pid_source)
2397: {
2398: switch(signal)
2399: {
2400: case rpl_signull:
2401: break;
2402:
2403: case rpl_sigint:
2404: signal_int(s_etat_processus, pid_source);
2405: break;
2406:
2407: case rpl_sigterm:
2408: signal_term(s_etat_processus, pid_source);
2409: break;
2410:
2411: case rpl_sigstart:
2412: signal_start(s_etat_processus, pid_source);
2413: break;
2414:
2415: case rpl_sigcont:
2416: signal_cont(s_etat_processus, pid_source);
2417: break;
2418:
2419: case rpl_sigstop:
2420: signal_stop(s_etat_processus, pid_source);
2421: break;
2422:
2423: case rpl_sigabort:
2424: signal_abort(s_etat_processus, pid_source);
2425: break;
2426:
2427: case rpl_sigurg:
2428: signal_urg(s_etat_processus, pid_source);
2429: break;
2430:
2431: case rpl_siginject:
2432: signal_inject(s_etat_processus, pid_source);
2433: break;
2434:
2435: case rpl_sigalrm:
2436: signal_alrm(s_etat_processus, pid_source);
2437: break;
2438:
2439: case rpl_sighup:
2440: signal_hup(s_etat_processus, pid_source);
2441: break;
2442:
2443: case rpl_sigtstp:
2444: signal_tstp(s_etat_processus, pid_source);
2445: break;
2446:
2447: case rpl_sigexcept:
2448: signal_except(s_etat_processus, pid_source);
2449: break;
2450:
2451: default:
2452: if ((*s_etat_processus).langue == 'F')
2453: {
2454: printf("+++System : Signal inconnu (%d) !\n", signal);
2455: }
2456: else
2457: {
2458: printf("+++System : Spurious signal (%d) !\n", signal);
2459: }
2460:
2461: break;
2462: }
2463:
2464: return;
2465: }
2466:
2467: void
2468: scrutation_interruptions(struct_processus *s_etat_processus)
2469: {
2470: // Interruptions qui arrivent sur le processus depuis un
2471: // processus externe.
2472:
2473: // Les pointeurs de lecture pointent sur les prochains éléments
2474: // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à
2475: // écrire.
2476:
2477: if (sem_trywait(semaphore_queue_signaux) == 0)
2478: {
2479: while((*s_queue_signaux).pointeur_lecture !=
2480: (*s_queue_signaux).pointeur_ecriture)
2481: {
2482: // Il y a un signal en attente dans le segment partagé. On le
2483: // traite.
2484:
2485: envoi_interruptions(s_etat_processus,
2486: (*s_queue_signaux).queue[(*s_queue_signaux)
2487: .pointeur_lecture].signal, (*s_queue_signaux).queue
2488: [(*s_queue_signaux).pointeur_lecture].pid);
2489: (*s_queue_signaux).pointeur_lecture =
2490: ((*s_queue_signaux).pointeur_lecture + 1)
2491: % LONGUEUR_QUEUE_SIGNAUX;
2492:
2493: # ifndef IPCS_SYSV
2494: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
2495: MS_ASYNC | MS_INVALIDATE) != 0)
2496: {
2497: sem_post(semaphore_queue_signaux);
2498: (*s_etat_processus).erreur_systeme = d_es_processus;
2499: return;
2500: }
2501: # endif
2502:
2503: while(sem_wait(semaphore_signalisation) != 0)
2504: {
2505: if (errno != EINTR)
2506: {
2507: (*s_etat_processus).erreur_systeme = d_es_processus;
2508: return;
2509: }
2510: }
2511: }
2512:
2513: sem_post(semaphore_queue_signaux);
2514: }
2515:
2516: // Interruptions qui arrivent depuis le groupe courant de threads.
2517:
2518: if (pthread_mutex_trylock(&mutex_liste_threads) == 0)
2519: {
2520: if (pthread_mutex_trylock(&((*s_etat_processus).mutex_signaux)) == 0)
2521: {
2522: while((*s_etat_processus).pointeur_signal_lecture !=
2523: (*s_etat_processus).pointeur_signal_ecriture)
2524: {
2525: // Il y a un signal dans la queue du thread courant.
2526: // On le traite.
2527:
2528: envoi_interruptions(s_etat_processus,
2529: (*s_etat_processus).signaux_en_queue
2530: [(*s_etat_processus).pointeur_signal_lecture],
2531: getpid());
2532: (*s_etat_processus).pointeur_signal_lecture =
2533: ((*s_etat_processus).pointeur_signal_lecture + 1)
2534: % LONGUEUR_QUEUE_SIGNAUX;
2535:
2536: while(sem_wait(semaphore_signalisation) != 0)
2537: {
2538: if (errno != EINTR)
2539: {
2540: if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
2541: {
2542: (*s_etat_processus).erreur_systeme = d_es_processus;
2543: return;
2544: }
2545:
2546: (*s_etat_processus).erreur_systeme = d_es_processus;
2547: return;
2548: }
2549: }
2550: }
2551:
2552: pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux));
2553: }
2554:
2555: pthread_mutex_unlock(&mutex_liste_threads);
2556: }
2557:
2558: return;
2559: }
2560:
2561:
2562: /*
2563: ================================================================================
2564: Fonction renvoyant le nom du segment de mémoire partagée en fonction
2565: du pid du processus.
2566: ================================================================================
2567: Entrée : Chemin absolue servant de racine, pid du processus
2568: --------------------------------------------------------------------------------
2569: Sortie : NULL ou nom du segment
2570: --------------------------------------------------------------------------------
2571: Effet de bord : Néant
2572: ================================================================================
2573: */
2574:
2575: static unsigned char *
2576: nom_segment(unsigned char *chemin, pid_t pid)
2577: {
2578: unsigned char *fichier;
2579:
2580: # ifdef IPCS_SYSV // !POSIX
2581: # ifndef OS2 // !OS2
2582:
2583: if ((fichier = sys_malloc((strlen(chemin) + 1 + 256 + 1) *
2584: sizeof(unsigned char))) == NULL)
2585: {
2586: return(NULL);
2587: }
2588:
2589: sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid);
2590: # else // OS2
2591: if ((fichier = sys_malloc((10 + 256 + 1) * sizeof(unsigned char)))
2592: == NULL)
2593: {
2594: return(NULL);
2595: }
2596:
2597: sprintf(fichier, "\\SHAREMEM\\RPL-SIGQUEUES-%d", (int) pid);
2598: # endif // OS2
2599: # else // POSIX
2600:
2601: if ((fichier = sys_malloc((1 + 256 + 1) *
2602: sizeof(unsigned char))) == NULL)
2603: {
2604: return(NULL);
2605: }
2606:
2607: sprintf(fichier, "/RPL-SIGQUEUES-%d", (int) pid);
2608: # endif
2609:
2610: return(fichier);
2611: }
2612:
2613:
2614: /*
2615: ================================================================================
2616: Fonctions d'envoi d'un signal à un thread ou à un processus.
2617: ================================================================================
2618: Entrée : processus et signal
2619: --------------------------------------------------------------------------------
2620: Sortie : erreur
2621: --------------------------------------------------------------------------------
2622: Effet de bord : Néant
2623: ================================================================================
2624: */
2625:
2626: int
2627: envoi_signal_processus(pid_t pid, enum signaux_rpl signal,
2628: logical1 test_ouverture)
2629: {
2630: # ifndef OS2
2631: int segment;
2632: # endif
2633:
2634: # ifndef IPCS_SYSV
2635: sem_t *semaphore;
2636: sem_t *signalisation;
2637: # else
2638: sem_t *semaphore;
2639: sem_t *signalisation;
2640: # ifndef OS2
2641: int desc;
2642: key_t clef;
2643: # endif
2644: # endif
2645:
2646: struct_queue_signaux *queue;
2647:
2648: struct timespec attente;
2649:
2650: unsigned char *nom;
2651:
2652: // Il s'agit d'ouvrir le segment de mémoire partagée, de le projeter en
2653: // mémoire puis d'y inscrire le signal à traiter.
2654:
2655: if (pid == getpid())
2656: {
2657: // Le signal est envoyé au même processus.
2658:
2659: if (s_queue_signaux == NULL)
2660: {
2661: return(1);
2662: }
2663:
2664: while(sem_wait(semaphore_queue_signaux) != 0)
2665: {
2666: if (errno != EINTR)
2667: {
2668: return(1);
2669: }
2670: }
2671:
2672: (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
2673: .pid = pid;
2674: (*s_queue_signaux).queue[(*s_queue_signaux).pointeur_ecriture]
2675: .signal = signal;
2676:
2677: (*s_queue_signaux).pointeur_ecriture =
2678: ((*s_queue_signaux).pointeur_ecriture + 1)
2679: % LONGUEUR_QUEUE_SIGNAUX;
2680:
2681: # ifndef IPCS_SYSV
2682: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
2683: MS_ASYNC | MS_INVALIDATE) != 0)
2684: {
2685: sem_post(semaphore_queue_signaux);
2686: return(1);
2687: }
2688: # endif
2689:
2690: if (sem_post(semaphore_queue_signaux) != 0)
2691: {
2692: return(1);
2693: }
2694:
2695: if (sem_post(semaphore_signalisation) != 0)
2696: {
2697: return(1);
2698: }
2699: }
2700: else
2701: {
2702: // Le signal est envoyé depuis un processus distinct.
2703:
2704: # ifdef IPCS_SYSV
2705: if ((nom = nom_segment(racine_segment, pid)) == NULL)
2706: {
2707: return(1);
2708: }
2709:
2710: # ifndef OS2 // SysV
2711: if (test_ouverture == d_vrai)
2712: {
2713: attente.tv_sec = 0;
2714: attente.tv_nsec = GRANULARITE_us * 1000;
2715:
2716: while((desc = open(nom, O_RDWR)) == -1)
2717: {
2718: nanosleep(&attente, NULL);
2719: INCR_GRANULARITE(attente.tv_nsec);
2720: }
2721: }
2722: else
2723: {
2724: if ((desc = open(nom, O_RDWR)) == -1)
2725: {
2726: sys_free(nom);
2727: return(1);
2728: }
2729: }
2730:
2731: close(desc);
2732:
2733: if ((clef = ftok(nom, 1)) == -1)
2734: {
2735: sys_free(nom);
2736: return(1);
2737: }
2738:
2739: sys_free(nom);
2740:
2741: if ((segment = shmget(clef, sizeof(struct_queue_signaux), 0))
2742: == -1)
2743: {
2744: return(1);
2745: }
2746:
2747: queue = shmat(segment, NULL, 0);
2748: # else // OS/2
2749: if (test_ouverture == d_vrai)
2750: {
2751: attente.tv_sec = 0;
2752: attente.tv_nsec = GRANULARITE_us * 1000;
2753:
2754: while(DosGetNamedSharedMem((PVOID) &queue, nom,
2755: PAG_WRITE | PAG_READ) != 0)
2756: {
2757: nanosleep(&attente, NULL);
2758: INCR_GRANULARITE(attente.tv_nsec);
2759: }
2760: }
2761: else
2762: {
2763: if (DosGetNamedSharedMem((PVOID) &queue, nom,
2764: PAG_WRITE | PAG_READ) != 0)
2765: {
2766: sys_free(nom);
2767: return(1);
2768: }
2769: }
2770:
2771: sys_free(nom);
2772: # endif
2773: # else // POSIX
2774: if ((nom = nom_segment(racine_segment, pid)) == NULL)
2775: {
2776: return(1);
2777: }
2778:
2779: if (test_ouverture == d_vrai)
2780: {
2781: attente.tv_sec = 0;
2782: attente.tv_nsec = GRANULARITE_us * 1000;
2783:
2784: while((segment = shm_open(nom, O_RDWR, 0)) == -1)
2785: {
2786: nanosleep(&attente, NULL);
2787: INCR_GRANULARITE(attente.tv_nsec);
2788: }
2789: }
2790: else
2791: {
2792: if ((segment = shm_open(nom, O_RDWR, 0)) == -1)
2793: {
2794: sys_free(nom);
2795: return(1);
2796: }
2797: }
2798:
2799: sys_free(nom);
2800:
2801: if ((queue = mmap(NULL, sizeof(struct_queue_signaux),
2802: PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0)) ==
2803: MAP_FAILED)
2804: {
2805: close(segment);
2806: return(1);
2807: }
2808: # endif
2809:
2810: // À ce moment, le segment de mémoire partagée est projeté
2811: // dans l'espace du processus.
2812:
2813: if ((semaphore = sem_open2(pid, SEM_QUEUE)) == SEM_FAILED)
2814: {
2815: # ifndef IPCS_SYSV // POSIX
2816: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2817: {
2818: munmap(queue, sizeof(struct_queue_signaux));
2819: close(segment);
2820: return(1);
2821: }
2822:
2823: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2824: {
2825: close(segment);
2826: return(1);
2827: }
2828:
2829: close(segment);
2830: # else // IPCS_SYSV
2831: # ifndef OS2 // SysV
2832: if (shmdt(queue) != 0)
2833: {
2834: return(1);
2835: }
2836: # else // OS/2
2837: // Pendant de DosGetNamedSHaredMem()
2838: # endif
2839: # endif
2840: return(1);
2841: }
2842:
2843: if ((signalisation = sem_open2(pid, SEM_SIGNALISATION))
2844: == SEM_FAILED)
2845: {
2846: # ifndef IPCS_SYSV // POSIX
2847: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2848: {
2849: munmap(queue, sizeof(struct_queue_signaux));
2850: close(segment);
2851: sem_close(semaphore);
2852: return(1);
2853: }
2854:
2855: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2856: {
2857: close(segment);
2858: sem_close(semaphore);
2859: return(1);
2860: }
2861:
2862: close(segment);
2863: # else // IPCS_SYSV
2864: # ifndef OS2 // SysV
2865: if (shmdt(queue) != 0)
2866: {
2867: sem_close(semaphore);
2868: return(1);
2869: }
2870: # else // OS/2
2871: // Pendant de DosGetNamedSHaredMem()
2872: # endif
2873: # endif
2874:
2875: sem_close(semaphore);
2876: return(1);
2877: }
2878:
2879: while(sem_wait(semaphore) != 0)
2880: {
2881: if (errno != EINTR)
2882: {
2883: # ifndef IPCS_SYSV // POSIX
2884: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE)
2885: != 0)
2886: {
2887: munmap(queue, sizeof(struct_queue_signaux));
2888: sem_close(semaphore);
2889: sem_close(signalisation);
2890: close(segment);
2891: return(1);
2892: }
2893:
2894: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2895: {
2896: sem_close(semaphore);
2897: sem_close(signalisation);
2898: close(segment);
2899: return(1);
2900: }
2901:
2902: close(segment);
2903: # else // IPCS_SYSV
2904: # ifndef OS2 // SysV
2905: if (shmdt(queue) != 0)
2906: {
2907: sem_close(semaphore);
2908: sem_close(signalisation);
2909: return(1);
2910: }
2911: # else // OS/2
2912: // Pendant de DosGetNamedSHaredMem()
2913: # endif
2914: # endif
2915:
2916: sem_close(semaphore);
2917: sem_close(signalisation);
2918: return(1);
2919: }
2920: }
2921:
2922: (*queue).queue[(*queue).pointeur_ecriture].pid = getpid();
2923: (*queue).queue[(*queue).pointeur_ecriture].signal = signal;
2924:
2925: (*queue).pointeur_ecriture = ((*queue).pointeur_ecriture + 1)
2926: % LONGUEUR_QUEUE_SIGNAUX;
2927:
2928: if (sem_post(semaphore) != 0)
2929: {
2930: # ifndef IPCS_SYSV // POSIX
2931: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2932: {
2933: munmap(queue, sizeof(struct_queue_signaux));
2934: close(segment);
2935: sem_close(semaphore);
2936: sem_close(signalisation);
2937: return(1);
2938: }
2939:
2940: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2941: {
2942: close(segment);
2943: sem_close(semaphore);
2944: sem_close(signalisation);
2945: return(1);
2946: }
2947:
2948: close(segment);
2949: # else // IPCS_SYSV
2950: # ifndef OS2 // SysV
2951: if (shmdt(queue) != 0)
2952: {
2953: sem_close(semaphore);
2954: sem_close(signalisation);
2955: return(1);
2956: }
2957: # else // OS/2
2958: // Pendant de DosGetNamedSHaredMem()
2959: # endif
2960: # endif
2961:
2962: sem_close(semaphore);
2963: sem_close(signalisation);
2964: return(1);
2965: }
2966:
2967: if (sem_close(semaphore) != 0)
2968: {
2969: # ifndef IPCS_SYSV // POSIX
2970: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
2971: {
2972: munmap(queue, sizeof(struct_queue_signaux));
2973: close(segment);
2974: sem_close(signalisation);
2975: return(1);
2976: }
2977:
2978: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
2979: {
2980: close(segment);
2981: sem_close(signalisation);
2982: return(1);
2983: }
2984:
2985: close(segment);
2986: # else // IPCS_SYSV
2987: # ifndef OS2 // SysV
2988: if (shmdt(queue) != 0)
2989: {
2990: sem_close(signalisation);
2991: return(1);
2992: }
2993: # else // OS/2
2994: // Pendant de DosGetNamedSHaredMem()
2995: # endif
2996: # endif
2997:
2998: sem_close(signalisation);
2999: return(1);
3000: }
3001:
3002: if (sem_post(signalisation) != 0)
3003: {
3004: # ifndef IPCS_SYSV // POSIX
3005: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3006: {
3007: munmap(queue, sizeof(struct_queue_signaux));
3008: close(segment);
3009: sem_close(signalisation);
3010: return(1);
3011: }
3012:
3013: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3014: {
3015: close(segment);
3016: sem_close(signalisation);
3017: return(1);
3018: }
3019:
3020: close(segment);
3021: # else // IPCS_SYSV
3022: # ifndef OS2 // SysV
3023: if (shmdt(queue) != 0)
3024: {
3025: sem_close(signalisation);
3026: return(1);
3027: }
3028: # else // OS/2
3029: // Pendant de DosGetNamedSHaredMem()
3030: # endif
3031: # endif
3032:
3033: sem_close(signalisation);
3034: return(1);
3035: }
3036:
3037: if (sem_close(signalisation) != 0)
3038: {
3039: # ifndef IPCS_SYSV // POSIX
3040: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3041: {
3042: munmap(queue, sizeof(struct_queue_signaux));
3043: close(segment);
3044: return(1);
3045: }
3046:
3047: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3048: {
3049: close(segment);
3050: return(1);
3051: }
3052:
3053: close(segment);
3054: # else // IPCS_SYSV
3055: # ifndef OS2 // SysV
3056: if (shmdt(queue) != 0)
3057: {
3058: return(1);
3059: }
3060: # else // OS/2
3061: // Pendant de DosGetNamedSHaredMem()
3062: # endif
3063: # endif
3064:
3065: return(1);
3066: }
3067:
3068: # ifndef IPCS_SYSV // POSIX
3069: if (msync(queue, sizeof(queue), MS_ASYNC | MS_INVALIDATE) != 0)
3070: {
3071: munmap(queue, sizeof(struct_queue_signaux));
3072: close(segment);
3073: return(1);
3074: }
3075:
3076: if (munmap(queue, sizeof(struct_queue_signaux)) != 0)
3077: {
3078: close(segment);
3079: return(1);
3080: }
3081:
3082: close(segment);
3083: # else // IPCS_SYSV
3084: # ifndef OS2 // SysV
3085: if (shmdt(queue) != 0)
3086: {
3087: return(1);
3088: }
3089: # else // OS/2
3090: // Pendant de DosGetNamedSHaredMem()
3091: # endif
3092: # endif
3093: }
3094:
3095: return(0);
3096: }
3097:
3098: int
3099: envoi_signal_thread(pthread_t tid, enum signaux_rpl signal)
3100: {
3101: // Un signal est envoyé d'un thread à un autre thread du même processus.
3102:
3103: volatile struct_liste_chainee_volatile *l_element_courant;
3104:
3105: struct_processus *s_etat_processus;
3106:
3107: if (pthread_mutex_lock(&mutex_liste_threads) != 0)
3108: {
3109: return(1);
3110: }
3111:
3112: l_element_courant = liste_threads;
3113:
3114: while(l_element_courant != NULL)
3115: {
3116: if (((*((struct_thread *) (*l_element_courant).donnee)).pid
3117: == getpid()) && (pthread_equal((*((struct_thread *)
3118: (*l_element_courant).donnee)).tid, tid) != 0))
3119: {
3120: break;
3121: }
3122:
3123: l_element_courant = (*l_element_courant).suivant;
3124: }
3125:
3126: if (l_element_courant == NULL)
3127: {
3128: pthread_mutex_unlock(&mutex_liste_threads);
3129: return(1);
3130: }
3131:
3132: s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee))
3133: .s_etat_processus;
3134:
3135: if (pthread_mutex_lock(&((*s_etat_processus).mutex_signaux)) != 0)
3136: {
3137: pthread_mutex_unlock(&mutex_liste_threads);
3138: return(1);
3139: }
3140:
3141: (*s_etat_processus).signaux_en_queue
3142: [(*s_etat_processus).pointeur_signal_ecriture] = signal;
3143: (*s_etat_processus).pointeur_signal_ecriture =
3144: ((*s_etat_processus).pointeur_signal_ecriture + 1)
3145: % LONGUEUR_QUEUE_SIGNAUX;
3146:
3147: if (pthread_mutex_unlock(&((*s_etat_processus).mutex_signaux)) != 0)
3148: {
3149: pthread_mutex_unlock(&mutex_liste_threads);
3150: return(1);
3151: }
3152:
3153: if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
3154: {
3155: return(1);
3156: }
3157:
3158: if (sem_post(semaphore_signalisation) != 0)
3159: {
3160: return(1);
3161: }
3162:
3163: return(0);
3164: }
3165:
3166: int
3167: envoi_signal_contexte(struct_processus *s_etat_processus_a_signaler,
3168: enum signaux_rpl signal)
3169: {
3170: pthread_mutex_lock(&((*s_etat_processus_a_signaler).mutex_signaux));
3171: (*s_etat_processus_a_signaler).signaux_en_queue
3172: [(*s_etat_processus_a_signaler).pointeur_signal_ecriture] =
3173: signal;
3174: (*s_etat_processus_a_signaler).pointeur_signal_ecriture =
3175: ((*s_etat_processus_a_signaler).pointeur_signal_ecriture + 1)
3176: % LONGUEUR_QUEUE_SIGNAUX;
3177: pthread_mutex_unlock(&((*s_etat_processus_a_signaler).mutex_signaux));
3178:
3179: if (sem_post(semaphore_signalisation) != 0)
3180: {
3181: return(1);
3182: }
3183:
3184: return(0);
3185: }
3186:
3187:
3188: /*
3189: ================================================================================
3190: Fonction créant un segment de mémoire partagée destiné à contenir
3191: la queue des signaux.
3192: ================================================================================
3193: Entrée : structure de description du processus
3194: --------------------------------------------------------------------------------
3195: Sortie : Néant
3196: --------------------------------------------------------------------------------
3197: Effet de bord : Néant
3198: ================================================================================
3199: */
3200:
3201: void
3202: creation_queue_signaux(struct_processus *s_etat_processus)
3203: {
3204: pthread_attr_t attributs;
3205:
3206: unsigned char *nom;
3207:
3208: racine_segment = (*s_etat_processus).chemin_fichiers_temporaires;
3209:
3210: # ifndef IPCS_SYSV // POSIX
3211: if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
3212: getpid())) == NULL)
3213: {
3214: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3215: return;
3216: }
3217:
3218: if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
3219: S_IRUSR | S_IWUSR)) == -1)
3220: {
3221: if (errno != EEXIST)
3222: {
3223: sys_free(nom);
3224: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3225: return;
3226: }
3227:
3228: if ((*s_etat_processus).langue == 'F')
3229: {
3230: printf("+++Attention : Le segment de mémoire %s préexiste !\n",
3231: nom);
3232: }
3233: else
3234: {
3235: printf("+++Warning: %s memory segment preexists!\n", nom);
3236: }
3237:
3238: if ((f_queue_signaux = shm_open(nom, O_RDWR | O_CREAT | O_TRUNC,
3239: S_IRUSR | S_IWUSR)) == -1)
3240: {
3241: sys_free(nom);
3242: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3243: return;
3244: }
3245: }
3246:
3247: if (ftruncate(f_queue_signaux, sizeof(struct_queue_signaux)) == -1)
3248: {
3249: sys_free(nom);
3250: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3251: return;
3252: }
3253:
3254: s_queue_signaux = mmap(NULL, sizeof(struct_queue_signaux),
3255: PROT_READ | PROT_WRITE, MAP_SHARED, f_queue_signaux, 0);
3256:
3257: if (((void *) s_queue_signaux) == ((void *) -1))
3258: {
3259: if (shm_unlink(nom) == -1)
3260: {
3261: sys_free(nom);
3262: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3263: return;
3264: }
3265:
3266: sys_free(nom);
3267: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3268: return;
3269: }
3270:
3271: sys_free(nom);
3272:
3273: if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
3274: == SEM_FAILED)
3275: {
3276: (*s_etat_processus).erreur_systeme = d_es_processus;
3277: return;
3278: }
3279:
3280: if ((semaphore_signalisation = sem_init2(0, getpid(),
3281: SEM_SIGNALISATION)) == SEM_FAILED)
3282: {
3283: (*s_etat_processus).erreur_systeme = d_es_processus;
3284: return;
3285: }
3286:
3287: if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
3288: SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
3289: {
3290: (*s_etat_processus).erreur_systeme = d_es_processus;
3291: return;
3292: }
3293:
3294: (*s_queue_signaux).pointeur_lecture = 0;
3295: (*s_queue_signaux).pointeur_ecriture = 0;
3296:
3297: (*s_queue_signaux).requete_arret = d_faux;
3298:
3299: if (msync(s_queue_signaux, sizeof(struct_queue_signaux),
3300: MS_ASYNC | MS_INVALIDATE) != 0)
3301: {
3302: (*s_etat_processus).erreur_systeme = d_es_processus;
3303: return;
3304: }
3305: # else // IPCS_SYSV
3306: # ifndef OS2
3307: int segment;
3308: int support;
3309:
3310: key_t clef;
3311:
3312: // Création d'un segment de données associé au PID du processus
3313: // courant
3314:
3315: if ((nom = nom_segment((*s_etat_processus)
3316: .chemin_fichiers_temporaires, getpid())) == NULL)
3317: {
3318: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3319: return;
3320: }
3321:
3322: if ((support = open(nom, O_RDWR | O_CREAT | O_EXCL,
3323: S_IRUSR | S_IWUSR)) == -1)
3324: {
3325: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
3326: return;
3327: }
3328:
3329: if ((clef = ftok(nom, 1)) == -1)
3330: {
3331: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3332: return;
3333: }
3334:
3335: close(support);
3336: sys_free(nom);
3337:
3338: if ((segment = shmget(clef, sizeof(struct_queue_signaux),
3339: IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
3340: {
3341: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3342: return;
3343: }
3344:
3345: s_queue_signaux = shmat(segment, NULL, 0);
3346: f_queue_signaux = segment;
3347:
3348: if (((void *) s_queue_signaux) == ((void *) -1))
3349: {
3350: if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
3351: {
3352: (*s_etat_processus).erreur_systeme =
3353: d_es_allocation_memoire;
3354: return;
3355: }
3356:
3357: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3358: return;
3359: }
3360:
3361: if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE))
3362: == SEM_FAILED)
3363: {
3364: (*s_etat_processus).erreur_systeme = d_es_processus;
3365: return;
3366: }
3367:
3368: if ((semaphore_signalisation = sem_init2(0, getpid(),
3369: SEM_SIGNALISATION)) == SEM_FAILED)
3370: {
3371: (*s_etat_processus).erreur_systeme = d_es_processus;
3372: return;
3373: }
3374:
3375: if ((semaphore_arret_signalisation = sem_init2(1, getpid(),
3376: SEM_ARRET_SIGNALISATION)) == SEM_FAILED)
3377: {
3378: (*s_etat_processus).erreur_systeme = d_es_processus;
3379: return;
3380: }
3381:
3382: (*s_queue_signaux).pointeur_lecture = 0;
3383: (*s_queue_signaux).pointeur_ecriture = 0;
3384: (*s_queue_signaux).requete_arret = d_faux;
3385: # else // OS/2
3386: if ((nom = nom_segment(NULL, getpid())) == NULL)
3387: {
3388: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3389: return;
3390: }
3391:
3392: if (DosAllocSharedMem((PVOID) &s_queue_signaux, nom,
3393: sizeof(struct_queue_signaux),
3394: PAG_WRITE | PAG_READ | PAG_COMMIT) != 0)
3395: {
3396: sys_free(nom);
3397: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3398: return;
3399: }
3400:
3401: sys_free(nom);
3402:
3403: sem_init(&((*s_queue_signaux).semaphore), 1, 1);
3404: sem_init(&((*s_queue_signaux).signalisation), 1, 0);
3405: sem_init(&((*s_queue_signaux).arret_signalisation), 1, 1);
3406:
3407: (*s_queue_signaux).pointeur_lecture = 0;
3408: (*s_queue_signaux).pointeur_ecriture = 0;
3409: (*s_queue_signaux).requete_arret = d_faux;
3410: # endif
3411: # endif
3412:
3413: // Lancement du thread de récupération des signaux.
3414:
3415: if (pthread_attr_init(&attributs) != 0)
3416: {
3417: (*s_etat_processus).erreur_systeme = d_es_processus;
3418: return;
3419: }
3420:
3421: if (pthread_attr_setdetachstate(&attributs,
3422: PTHREAD_CREATE_JOINABLE) != 0)
3423: {
3424: (*s_etat_processus).erreur_systeme = d_es_processus;
3425: return;
3426: }
3427:
3428: if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs,
3429: thread_surveillance_signaux, s_etat_processus) != 0)
3430: {
3431: (*s_etat_processus).erreur_systeme = d_es_processus;
3432: return;
3433: }
3434:
3435: if (pthread_attr_destroy(&attributs) != 0)
3436: {
3437: (*s_etat_processus).erreur_systeme = d_es_processus;
3438: return;
3439: }
3440:
3441: (*s_queue_signaux).controle = getpid();
3442:
3443: # ifndef IPCS_SYSV
3444: if (msync(s_queue_signaux, sizeof(s_queue_signaux),
3445: MS_ASYNC | MS_INVALIDATE) != 0)
3446: {
3447: (*s_etat_processus).erreur_systeme = d_es_processus;
3448: return;
3449: }
3450: # endif
3451:
3452: if (lancement_thread_signaux(s_etat_processus) == d_erreur)
3453: {
3454: (*s_etat_processus).erreur_systeme = d_es_processus;
3455: return;
3456: }
3457:
3458: return;
3459: }
3460:
3461:
3462: /*
3463: ================================================================================
3464: Fonction libérant le segment de mémoire partagée destiné à contenir
3465: la queue des signaux.
3466: ================================================================================
3467: Entrée : structure de description du processus
3468: --------------------------------------------------------------------------------
3469: Sortie : Néant
3470: --------------------------------------------------------------------------------
3471: Effet de bord : Néant
3472: ================================================================================
3473: */
3474:
3475: void
3476: liberation_queue_signaux(struct_processus *s_etat_processus)
3477: {
3478: # ifdef IPCS_SYSV // SystemV
3479: # ifndef OS2
3480: if (shmdt(s_queue_signaux) == -1)
3481: {
3482: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3483: return;
3484: }
3485: # else // OS/2
3486: # endif
3487: # else // POSIX
3488: sem_close(semaphore_queue_signaux);
3489: sem_close(semaphore_signalisation);
3490: sem_close(semaphore_arret_signalisation);
3491:
3492: if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
3493: {
3494: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3495: return;
3496: }
3497:
3498: close(f_queue_signaux);
3499: # endif
3500:
3501: return;
3502: }
3503:
3504:
3505: /*
3506: ================================================================================
3507: Fonction détruisant le segment de mémoire partagée destiné à contenir
3508: la queue des signaux.
3509: ================================================================================
3510: Entrée : structure de description du processus
3511: --------------------------------------------------------------------------------
3512: Sortie : Néant
3513: --------------------------------------------------------------------------------
3514: Effet de bord : Néant
3515: ================================================================================
3516: */
3517:
3518: void
3519: destruction_queue_signaux(struct_processus *s_etat_processus)
3520: {
3521: # ifndef OS2
3522: unsigned char *nom;
3523: # endif
3524:
3525: while(sem_wait(semaphore_arret_signalisation) != 0)
3526: {
3527: if (errno != EINTR)
3528: {
3529: (*s_etat_processus).erreur_systeme = d_es_processus;
3530: return;
3531: }
3532: }
3533:
3534: (*s_queue_signaux).requete_arret = d_vrai;
3535:
3536: # ifndef IPCS_SYSV
3537: msync(s_queue_signaux, sizeof(s_queue_signaux), MS_ASYNC | MS_INVALIDATE);
3538: # endif
3539:
3540: sem_post(semaphore_arret_signalisation);
3541:
3542: // Incrémenter le sémaphore pour être sûr de le débloquer.
3543:
3544: sem_post(semaphore_signalisation);
3545: pthread_join((*s_queue_signaux).thread_signaux, NULL);
3546: arret_thread_signaux(s_etat_processus);
3547:
3548: # ifdef IPCS_SYSV // SystemV
3549: # ifndef OS2
3550: // Il faut commencer par éliminer le sémaphore.
3551:
3552: if (semctl((*semaphore_queue_signaux).sem, 0, IPC_RMID) == -1)
3553: {
3554: (*s_etat_processus).erreur_systeme = d_es_processus;
3555: return;
3556: }
3557:
3558: unlink((*semaphore_queue_signaux).path);
3559: sys_free((*semaphore_queue_signaux).path);
3560:
3561: if (semctl((*semaphore_signalisation).sem, 0, IPC_RMID) == -1)
3562: {
3563: (*s_etat_processus).erreur_systeme = d_es_processus;
3564: return;
3565: }
3566:
3567: unlink((*semaphore_signalisation).path);
3568: sys_free((*semaphore_signalisation).path);
3569:
3570: if (semctl((*semaphore_arret_signalisation).sem, 0, IPC_RMID) == -1)
3571: {
3572: (*s_etat_processus).erreur_systeme = d_es_processus;
3573: return;
3574: }
3575:
3576: unlink((*semaphore_arret_signalisation).path);
3577: sys_free((*semaphore_arret_signalisation).path);
3578:
3579: if (shmdt(s_queue_signaux) == -1)
3580: {
3581: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3582: return;
3583: }
3584:
3585: if (shmctl(f_queue_signaux, IPC_RMID, 0) == -1)
3586: {
3587: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3588: return;
3589: }
3590:
3591: if ((nom = nom_segment((*s_etat_processus)
3592: .chemin_fichiers_temporaires, getpid())) == NULL)
3593: {
3594: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3595: return;
3596: }
3597:
3598: unlink(nom);
3599: sys_free(nom);
3600: # else
3601: sem_close(&((*s_queue_signaux).semaphore));
3602: sem_destroy(&((*s_queue_signaux).semaphore));
3603:
3604: sem_close(&((*s_queue_signaux).signalisation));
3605: sem_destroy(&((*s_queue_signaux).signalisation));
3606:
3607: sem_close(&((*s_queue_signaux).arret_signalisation));
3608: sem_destroy(&((*s_queue_signaux).arret_signalisation));
3609:
3610: if (DosFreeMem(s_queue_signaux) != 0)
3611: {
3612: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3613: return;
3614: }
3615: # endif
3616: # else // POSIX
3617: sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE);
3618: sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION);
3619: sem_destroy2(semaphore_arret_signalisation, getpid(),
3620: SEM_ARRET_SIGNALISATION);
3621:
3622: if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)
3623: {
3624: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3625: return;
3626: }
3627:
3628: if ((nom = nom_segment(NULL, getpid())) == NULL)
3629: {
3630: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3631: return;
3632: }
3633:
3634: close(f_queue_signaux);
3635:
3636: if (shm_unlink(nom) != 0)
3637: {
3638: sys_free(nom);
3639: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
3640: return;
3641: }
3642:
3643: sys_free(nom);
3644: # endif
3645:
3646: return;
3647: }
3648:
3649: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>