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