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