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