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