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