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