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