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