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