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