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