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