File:
[local] /
rpl /
src /
interruptions.c
Revision
1.11:
download - view:
text,
annotated -
select for diffs -
revision graph
Thu Apr 29 07:30:58 2010 UTC (14 years ago) by
bertrand
Branches:
MAIN
CVS tags:
HEAD
Correction d'un point bloquant dans la gestion des processus
(affectation des interruptions logicielles survenant après l'arrêt du
processus père car le mutex de protection de la routine était déjà positionné
dans la fonction appelante). Ajout de la fonction CLRATEXIT.
1: /*
2: ================================================================================
3: RPL/2 (R) version 4.0.15
4: Copyright (C) 1989-2010 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:
56: static volatile struct_liste_chainee_volatile *liste_threads
57: = NULL;
58: static volatile struct_liste_chainee_volatile *liste_threads_surveillance
59: = NULL;
60:
61: void
62: modification_pid_thread_pere(struct_processus *s_etat_processus)
63: {
64: // La variable existe toujours et aucun thread concurrent ne peut
65: // la modifier puisque cette routine ne peut être appelée que depuis
66: // DAEMON.
67:
68: (*((struct_thread *) (*liste_threads).donnee)).pid =
69: (*s_etat_processus).pid_processus_pere;
70:
71: return;
72: }
73:
74: void
75: insertion_thread(struct_processus *s_etat_processus, logical1 thread_principal)
76: {
77: sigset_t oldset;
78: sigset_t set;
79:
80: volatile struct_liste_chainee_volatile *l_nouvel_objet;
81:
82: sigfillset(&set);
83: pthread_sigmask(SIG_BLOCK, &set, &oldset);
84:
85: # ifndef SEMAPHORES_NOMMES
86: while(sem_wait(&semaphore_liste_threads) == -1)
87: # else
88: while(sem_wait(semaphore_liste_threads) == -1)
89: # endif
90: {
91: if (errno != EINTR)
92: {
93: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
94: sigpending(&set);
95:
96: (*s_etat_processus).erreur_systeme = d_es_processus;
97: return;
98: }
99: }
100:
101: if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
102: == NULL)
103: {
104: # ifndef SEMAPHORES_NOMMES
105: sem_post(&semaphore_liste_threads);
106: # else
107: sem_post(semaphore_liste_threads);
108: # endif
109: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
110: sigpending(&set);
111:
112: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
113: return;
114: }
115:
116: (*l_nouvel_objet).suivant = liste_threads;
117:
118: if (((*l_nouvel_objet).donnee = malloc(sizeof(struct_thread))) == NULL)
119: {
120: # ifndef SEMAPHORES_NOMMES
121: sem_post(&semaphore_liste_threads);
122: # else
123: sem_post(semaphore_liste_threads);
124: # endif
125: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
126: sigpending(&set);
127:
128: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
129: return;
130: }
131:
132: (*((struct_thread *) (*l_nouvel_objet).donnee)).pid = getpid();
133: (*((struct_thread *) (*l_nouvel_objet).donnee)).tid = pthread_self();
134: (*((struct_thread *) (*l_nouvel_objet).donnee)).thread_principal =
135: thread_principal;
136: (*((struct_thread *) (*l_nouvel_objet).donnee)).s_etat_processus =
137: s_etat_processus;
138:
139: liste_threads = l_nouvel_objet;
140:
141: # ifndef SEMAPHORES_NOMMES
142: if (sem_post(&semaphore_liste_threads) != 0)
143: # else
144: if (sem_post(semaphore_liste_threads) != 0)
145: # endif
146: {
147: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
148: sigpending(&set);
149:
150: (*s_etat_processus).erreur_systeme = d_es_processus;
151: return;
152: }
153:
154: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
155: sigpending(&set);
156: return;
157: }
158:
159: void
160: insertion_thread_surveillance(struct_processus *s_etat_processus,
161: struct_descripteur_thread *s_argument_thread)
162: {
163: sigset_t oldset;
164: sigset_t set;
165:
166: volatile struct_liste_chainee_volatile *l_nouvel_objet;
167:
168: sigfillset(&set);
169: pthread_sigmask(SIG_BLOCK, &set, &oldset);
170:
171: # ifndef SEMAPHORES_NOMMES
172: while(sem_wait(&semaphore_liste_threads) == -1)
173: # else
174: while(sem_wait(semaphore_liste_threads) == -1)
175: # endif
176: {
177: if (errno != EINTR)
178: {
179: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
180: sigpending(&set);
181:
182: (*s_etat_processus).erreur_systeme = d_es_processus;
183: return;
184: }
185: }
186:
187: if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile)))
188: == NULL)
189: {
190: # ifndef SEMAPHORES_NOMMES
191: sem_post(&semaphore_liste_threads);
192: # else
193: sem_post(semaphore_liste_threads);
194: # endif
195: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
196: sigpending(&set);
197:
198: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
199: return;
200: }
201:
202: (*l_nouvel_objet).suivant = liste_threads_surveillance;
203: (*l_nouvel_objet).donnee = (void *) s_argument_thread;
204:
205: liste_threads_surveillance = l_nouvel_objet;
206:
207: # ifndef SEMAPHORES_NOMMES
208: if (sem_post(&semaphore_liste_threads) != 0)
209: # else
210: if (sem_post(semaphore_liste_threads) != 0)
211: # endif
212: {
213: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
214: sigpending(&set);
215:
216: (*s_etat_processus).erreur_systeme = d_es_processus;
217: return;
218: }
219:
220: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
221: sigpending(&set);
222: return;
223: }
224:
225: void
226: retrait_thread(struct_processus *s_etat_processus)
227: {
228: sigset_t oldset;
229: sigset_t set;
230:
231: volatile struct_liste_chainee_volatile *l_element_precedent;
232: volatile struct_liste_chainee_volatile *l_element_courant;
233:
234: sigfillset(&set);
235: pthread_sigmask(SIG_BLOCK, &set, &oldset);
236:
237: # ifndef SEMAPHORES_NOMMES
238: while(sem_wait(&semaphore_liste_threads) == -1)
239: # else
240: while(sem_wait(semaphore_liste_threads) == -1)
241: # endif
242: {
243: if (errno != EINTR)
244: {
245: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
246: sigpending(&set);
247:
248: (*s_etat_processus).erreur_systeme = d_es_processus;
249: return;
250: }
251: }
252:
253: l_element_precedent = NULL;
254: l_element_courant = liste_threads;
255:
256: while(l_element_courant != NULL)
257: {
258: if (((*((struct_thread *) (*l_element_courant).donnee)).pid
259: == getpid()) && (pthread_equal((*((struct_thread *)
260: (*l_element_courant).donnee)).tid, pthread_self()) != 0))
261: {
262: break;
263: }
264:
265: l_element_precedent = l_element_courant;
266: l_element_courant = (*l_element_courant).suivant;
267: }
268:
269: if (l_element_courant == NULL)
270: {
271: # ifndef SEMAPHORES_NOMMES
272: sem_post(&semaphore_liste_threads);
273: # else
274: sem_post(semaphore_liste_threads);
275: # endif
276: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
277: sigpending(&set);
278:
279: (*s_etat_processus).erreur_systeme = d_es_processus;
280: return;
281: }
282:
283: if (l_element_precedent == NULL)
284: {
285: liste_threads = (*l_element_courant).suivant;
286: }
287: else
288: {
289: (*l_element_precedent).suivant = (*l_element_courant).suivant;
290: }
291:
292: free((void *) (*l_element_courant).donnee);
293: free((struct_liste_chainee_volatile *) l_element_courant);
294:
295: if (pthread_setspecific(semaphore_fork_processus_courant, NULL) != 0)
296: {
297: (*s_etat_processus).erreur_systeme = d_es_processus;
298:
299: # ifndef SEMAPHORES_NOMMES
300: sem_post(&semaphore_liste_threads);
301: # else
302: sem_post(semaphore_liste_threads);
303: # endif
304: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
305: sigpending(&set);
306: return;
307: }
308:
309: # ifndef SEMAPHORES_NOMMES
310: if (sem_post(&semaphore_liste_threads) != 0)
311: # else
312: if (sem_post(semaphore_liste_threads) != 0)
313: # endif
314: {
315: (*s_etat_processus).erreur_systeme = d_es_processus;
316:
317: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
318: sigpending(&set);
319: return;
320: }
321:
322: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
323: sigpending(&set);
324: return;
325: }
326:
327: void
328: retrait_thread_surveillance(struct_processus *s_etat_processus,
329: struct_descripteur_thread *s_argument_thread)
330: {
331: sigset_t set;
332: sigset_t oldset;
333:
334: volatile struct_liste_chainee_volatile *l_element_precedent;
335: volatile struct_liste_chainee_volatile *l_element_courant;
336:
337: sigfillset(&set);
338: pthread_sigmask(SIG_BLOCK, &set, &oldset);
339:
340: # ifndef SEMAPHORES_NOMMES
341: while(sem_wait(&semaphore_liste_threads) == -1)
342: # else
343: while(sem_wait(semaphore_liste_threads) == -1)
344: # endif
345: {
346: if (errno != EINTR)
347: {
348: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
349: sigpending(&set);
350:
351: (*s_etat_processus).erreur_systeme = d_es_processus;
352: return;
353: }
354: }
355:
356: l_element_precedent = NULL;
357: l_element_courant = liste_threads_surveillance;
358:
359: while(l_element_courant != NULL)
360: {
361: if ((*l_element_courant).donnee == (void *) s_argument_thread)
362: {
363: break;
364: }
365:
366: l_element_precedent = l_element_courant;
367: l_element_courant = (*l_element_courant).suivant;
368: }
369:
370: if (l_element_courant == NULL)
371: {
372: # ifndef SEMAPHORES_NOMMES
373: sem_post(&semaphore_liste_threads);
374: # else
375: sem_post(semaphore_liste_threads);
376: # endif
377: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
378: sigpending(&set);
379:
380: (*s_etat_processus).erreur_systeme = d_es_processus;
381: return;
382: }
383:
384: if (l_element_precedent == NULL)
385: {
386: liste_threads_surveillance = (*l_element_courant).suivant;
387: }
388: else
389: {
390: (*l_element_precedent).suivant = (*l_element_courant).suivant;
391: }
392:
393: free((struct_liste_chainee_volatile *) l_element_courant);
394:
395: if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)
396: {
397: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
398: sigpending(&set);
399:
400: (*s_etat_processus).erreur_systeme = d_es_processus;
401: return;
402: }
403:
404: (*s_argument_thread).nombre_references--;
405:
406: BUG((*s_argument_thread).nombre_references < 0,
407: printf("(*s_argument_thread).nombre_references = %d\n",
408: (int) (*s_argument_thread).nombre_references));
409:
410: if ((*s_argument_thread).nombre_references == 0)
411: {
412: if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)
413: {
414: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
415: sigpending(&set);
416:
417: (*s_etat_processus).erreur_systeme = d_es_processus;
418: return;
419: }
420:
421: pthread_mutex_destroy(&((*s_argument_thread).mutex));
422: free(s_argument_thread);
423: }
424: else
425: {
426: if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)
427: {
428: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
429: sigpending(&set);
430:
431: (*s_etat_processus).erreur_systeme = d_es_processus;
432: return;
433: }
434: }
435:
436: # ifndef SEMAPHORES_NOMMES
437: if (sem_post(&semaphore_liste_threads) != 0)
438: # else
439: if (sem_post(semaphore_liste_threads) != 0)
440: # endif
441: {
442: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
443: sigpending(&set);
444:
445: (*s_etat_processus).erreur_systeme = d_es_processus;
446: return;
447: }
448:
449: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
450: sigpending(&set);
451: return;
452: }
453:
454: void
455: verrouillage_threads_concurrents(struct_processus *s_etat_processus)
456: {
457: volatile struct_liste_chainee_volatile *l_element_courant;
458:
459: # ifndef SEMAPHORES_NOMMES
460: while(sem_wait(&semaphore_liste_threads) == -1)
461: # else
462: while(sem_wait(semaphore_liste_threads) == -1)
463: # endif
464: {
465: if (errno != EINTR)
466: {
467: (*s_etat_processus).erreur_systeme = d_es_processus;
468: return;
469: }
470: }
471:
472: l_element_courant = liste_threads;
473:
474: while(l_element_courant != NULL)
475: {
476: if (((*((struct_thread *) (*l_element_courant).donnee)).pid
477: == getpid()) && (pthread_equal((*((struct_thread *)
478: (*l_element_courant).donnee)).tid, pthread_self()) == 0))
479: {
480: # ifndef SEMAPHORES_NOMMES
481: while(sem_wait(&((*(*((struct_thread *) (*l_element_courant)
482: .donnee)).s_etat_processus).semaphore_fork)) == -1)
483: # else
484: while(sem_wait((*(*((struct_thread *) (*l_element_courant)
485: .donnee)).s_etat_processus).semaphore_fork) == -1)
486: # endif
487: {
488: if (errno != EINTR)
489: {
490: (*s_etat_processus).erreur_systeme = d_es_processus;
491: return;
492: }
493: }
494: }
495:
496: l_element_courant = (*l_element_courant).suivant;
497: }
498:
499: return;
500: }
501:
502: void
503: deverrouillage_threads_concurrents(struct_processus *s_etat_processus)
504: {
505: volatile struct_liste_chainee_volatile *l_element_courant;
506:
507: l_element_courant = liste_threads;
508:
509: while(l_element_courant != NULL)
510: {
511: if (((*((struct_thread *) (*l_element_courant).donnee)).pid
512: == getpid()) && (pthread_equal((*((struct_thread *)
513: (*l_element_courant).donnee)).tid, pthread_self()) == 0))
514: {
515: # ifndef SEMAPHORES_NOMMES
516: if (sem_post(&((*(*((struct_thread *)
517: (*l_element_courant).donnee)).s_etat_processus)
518: .semaphore_fork)) != 0)
519: # else
520: if (sem_post((*(*((struct_thread *)
521: (*l_element_courant).donnee)).s_etat_processus)
522: .semaphore_fork) != 0)
523: # endif
524: {
525: # ifndef SEMAPHORES_NOMMES
526: if (sem_post(&semaphore_liste_threads) != 0)
527: {
528: (*s_etat_processus).erreur_systeme = d_es_processus;
529: return;
530: }
531: # else
532: if (sem_post(semaphore_liste_threads) != 0)
533: {
534: (*s_etat_processus).erreur_systeme = d_es_processus;
535: return;
536: }
537: # endif
538:
539: (*s_etat_processus).erreur_systeme = d_es_processus;
540: return;
541: }
542: }
543:
544: l_element_courant = (*l_element_courant).suivant;
545: }
546:
547: # ifndef SEMAPHORES_NOMMES
548: if (sem_post(&semaphore_liste_threads) != 0)
549: # else
550: if (sem_post(semaphore_liste_threads) != 0)
551: # endif
552: {
553: (*s_etat_processus).erreur_systeme = d_es_processus;
554: return;
555: }
556:
557: return;
558: }
559:
560: void
561: liberation_threads(struct_processus *s_etat_processus)
562: {
563: logical1 suppression_variables_partagees;
564:
565: sigset_t oldset;
566: sigset_t set;
567:
568: struct_descripteur_thread *s_argument_thread;
569:
570: struct_processus *candidat;
571:
572: unsigned long i;
573:
574: void *element_candidat;
575: void *element_courant;
576: void *element_suivant;
577:
578: volatile struct_liste_chainee_volatile *l_element_courant;
579: volatile struct_liste_chainee_volatile *l_element_suivant;
580:
581: sigfillset(&set);
582: pthread_sigmask(SIG_BLOCK, &set, &oldset);
583:
584: # ifndef SEMAPHORES_NOMMES
585: while(sem_wait(&semaphore_liste_threads) == -1)
586: # else
587: while(sem_wait(semaphore_liste_threads) == -1)
588: # endif
589: {
590: if (errno != EINTR)
591: {
592: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
593: (*s_etat_processus).erreur_systeme = d_es_processus;
594: return;
595: }
596: }
597:
598: l_element_courant = liste_threads;
599: suppression_variables_partagees = d_faux;
600:
601: while(l_element_courant != NULL)
602: {
603: if ((*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus
604: != s_etat_processus)
605: {
606: candidat = s_etat_processus;
607: s_etat_processus = (*((struct_thread *)
608: (*l_element_courant).donnee)).s_etat_processus;
609: free((*s_etat_processus).localisation);
610:
611: // (*s_etat_processus).instruction_courante peut pointer sur
612: // n'importe quoi (une instruction courante ou un champ d'une
613: // structure objet). On ne le libère pas quitte à avoir une
614: // petite fuite mémoire dans le processus fils.
615:
616: if ((*s_etat_processus).instruction_courante != NULL)
617: {
618: //free((*s_etat_processus).instruction_courante);
619: }
620:
621: close((*s_etat_processus).pipe_acquittement);
622: close((*s_etat_processus).pipe_donnees);
623: close((*s_etat_processus).pipe_injections);
624: close((*s_etat_processus).pipe_nombre_injections);
625: close((*s_etat_processus).pipe_interruptions);
626: close((*s_etat_processus).pipe_nombre_objets_attente);
627: close((*s_etat_processus).pipe_nombre_interruptions_attente);
628:
629: if ((*s_etat_processus).nom_fichier_impression != NULL)
630: {
631: free((*s_etat_processus).nom_fichier_impression);
632: }
633:
634: while((*s_etat_processus).fichiers_graphiques != NULL)
635: {
636: free((*(*s_etat_processus).fichiers_graphiques).nom);
637:
638: if ((*(*s_etat_processus).fichiers_graphiques).legende != NULL)
639: {
640: free((*(*s_etat_processus).fichiers_graphiques).legende);
641: }
642:
643: element_courant = (*s_etat_processus).fichiers_graphiques;
644: (*s_etat_processus).fichiers_graphiques =
645: (*(*s_etat_processus).fichiers_graphiques).suivant;
646:
647: free(element_courant);
648: }
649:
650: if ((*s_etat_processus).entree_standard != NULL)
651: {
652: pclose((*s_etat_processus).entree_standard);
653: }
654:
655: if ((*s_etat_processus).generateur_aleatoire != NULL)
656: {
657: liberation_generateur_aleatoire(s_etat_processus);
658: }
659:
660: if ((*s_etat_processus).instruction_derniere_erreur != NULL)
661: {
662: free((*s_etat_processus).instruction_derniere_erreur);
663: (*s_etat_processus).instruction_derniere_erreur = NULL;
664: }
665:
666: element_courant = (void *) (*s_etat_processus)
667: .l_base_pile_processus;
668: while(element_courant != NULL)
669: {
670: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
671: element_courant)).donnee).mutex));
672: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
673: element_courant)).donnee).mutex));
674: liberation(s_etat_processus,
675: (*((struct_liste_chainee *) element_courant)).donnee);
676: element_suivant = (*((struct_liste_chainee *) element_courant))
677: .suivant;
678: free((struct_liste_chainee *) element_courant);
679: element_courant = element_suivant;
680: }
681:
682: pthread_mutex_trylock(&((*(*s_etat_processus).indep).mutex));
683: pthread_mutex_unlock(&((*(*s_etat_processus).indep).mutex));
684: liberation(s_etat_processus, (*s_etat_processus).indep);
685:
686: pthread_mutex_trylock(&((*(*s_etat_processus).depend).mutex));
687: pthread_mutex_unlock(&((*(*s_etat_processus).depend).mutex));
688: liberation(s_etat_processus, (*s_etat_processus).depend);
689:
690: free((*s_etat_processus).label_x);
691: free((*s_etat_processus).label_y);
692: free((*s_etat_processus).label_z);
693: free((*s_etat_processus).titre);
694: free((*s_etat_processus).legende);
695:
696: pthread_mutex_trylock(&((*(*s_etat_processus)
697: .parametres_courbes_de_niveau).mutex));
698: pthread_mutex_unlock(&((*(*s_etat_processus)
699: .parametres_courbes_de_niveau).mutex));
700: liberation(s_etat_processus, (*s_etat_processus)
701: .parametres_courbes_de_niveau);
702:
703: for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++)
704: {
705: if ((*s_etat_processus).corps_interruptions[i] != NULL)
706: {
707: pthread_mutex_trylock(&((*(*s_etat_processus)
708: .corps_interruptions[i]).mutex));
709: pthread_mutex_unlock(&((*(*s_etat_processus)
710: .corps_interruptions[i]).mutex));
711:
712: liberation(s_etat_processus,
713: (*s_etat_processus).corps_interruptions[i]);
714: }
715:
716: element_courant = (*s_etat_processus)
717: .pile_origine_interruptions[i];
718:
719: while(element_courant != NULL)
720: {
721: element_suivant = (*((struct_liste_chainee *)
722: element_courant)).suivant;
723:
724: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
725: element_courant)).donnee).mutex));
726: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
727: element_courant)).donnee).mutex));
728:
729: liberation(s_etat_processus,
730: (*((struct_liste_chainee *) element_courant))
731: .donnee);
732: free(element_courant);
733:
734: element_courant = element_suivant;
735: }
736: }
737:
738: for(i = 0; i < (*s_etat_processus).nombre_variables; i++)
739: {
740: pthread_mutex_trylock(&((*(*s_etat_processus)
741: .s_liste_variables[i].objet).mutex));
742: pthread_mutex_unlock(&((*(*s_etat_processus)
743: .s_liste_variables[i].objet).mutex));
744:
745: // Les variables de niveau 0 sont des définitions qui
746: // ne sont pas copiées entre threads.
747: if ((*s_etat_processus).s_liste_variables[i].niveau > 0)
748: {
749: liberation(s_etat_processus,
750: (*s_etat_processus).s_liste_variables[i].objet);
751: }
752:
753: free((*s_etat_processus).s_liste_variables[i].nom);
754: }
755:
756: free((*s_etat_processus).s_liste_variables);
757:
758: for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++)
759: {
760: pthread_mutex_trylock(&((*(*s_etat_processus)
761: .s_liste_variables_statiques[i].objet).mutex));
762: pthread_mutex_unlock(&((*(*s_etat_processus)
763: .s_liste_variables_statiques[i].objet).mutex));
764:
765: liberation(s_etat_processus, (*s_etat_processus)
766: .s_liste_variables_statiques[i].objet);
767: free((*s_etat_processus).s_liste_variables_statiques[i].nom);
768: }
769:
770: free((*s_etat_processus).s_liste_variables_statiques);
771:
772: // Ne peut être effacé qu'une seule fois
773: if (suppression_variables_partagees == d_faux)
774: {
775: suppression_variables_partagees = d_vrai;
776:
777: for(i = 0; i < (*(*s_etat_processus)
778: .s_liste_variables_partagees).nombre_variables; i++)
779: {
780: pthread_mutex_trylock(&((*(*(*s_etat_processus)
781: .s_liste_variables_partagees).table[i].objet)
782: .mutex));
783: pthread_mutex_unlock(&((*(*(*s_etat_processus)
784: .s_liste_variables_partagees).table[i].objet)
785: .mutex));
786:
787: liberation(s_etat_processus, (*(*s_etat_processus)
788: .s_liste_variables_partagees).table[i].objet);
789: free((*(*s_etat_processus).s_liste_variables_partagees)
790: .table[i].nom);
791: }
792:
793: if ((*(*s_etat_processus).s_liste_variables_partagees).table
794: != NULL)
795: {
796: free((struct_variable_partagee *) (*(*s_etat_processus)
797: .s_liste_variables_partagees).table);
798: }
799:
800: pthread_mutex_trylock(&((*(*s_etat_processus)
801: .s_liste_variables_partagees).mutex));
802: pthread_mutex_unlock(&((*(*s_etat_processus)
803: .s_liste_variables_partagees).mutex));
804: }
805:
806: element_courant = (*s_etat_processus).l_base_pile;
807: while(element_courant != NULL)
808: {
809: element_suivant = (*((struct_liste_chainee *)
810: element_courant)).suivant;
811:
812: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
813: element_courant)).donnee).mutex));
814: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
815: element_courant)).donnee).mutex));
816:
817: liberation(s_etat_processus,
818: (*((struct_liste_chainee *)
819: element_courant)).donnee);
820: free((struct_liste_chainee *) element_courant);
821:
822: element_courant = element_suivant;
823: }
824:
825: element_courant = (*s_etat_processus).l_base_pile_contextes;
826: while(element_courant != NULL)
827: {
828: element_suivant = (*((struct_liste_chainee *)
829: element_courant)).suivant;
830:
831: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
832: element_courant)).donnee).mutex));
833: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
834: element_courant)).donnee).mutex));
835: liberation(s_etat_processus, (*((struct_liste_chainee *)
836: element_courant)).donnee);
837: free((struct_liste_chainee *) element_courant);
838:
839: element_courant = element_suivant;
840: }
841:
842: element_courant = (*s_etat_processus).l_base_pile_taille_contextes;
843: while(element_courant != NULL)
844: {
845: element_suivant = (*((struct_liste_chainee *)
846: element_courant)).suivant;
847:
848: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
849: element_courant)).donnee).mutex));
850: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
851: element_courant)).donnee).mutex));
852: liberation(s_etat_processus,
853: (*((struct_liste_chainee *)
854: element_courant)).donnee);
855: free((struct_liste_chainee *) element_courant);
856:
857: element_courant = element_suivant;
858: }
859:
860: for(i = 0; i < (*s_etat_processus).nombre_instructions_externes;
861: i++)
862: {
863: free((*s_etat_processus).s_instructions_externes[i].nom);
864: free((*s_etat_processus).s_instructions_externes[i]
865: .nom_bibliotheque);
866: }
867:
868: if ((*s_etat_processus).nombre_instructions_externes != 0)
869: {
870: free((*s_etat_processus).s_instructions_externes);
871: }
872:
873: element_courant = (*s_etat_processus).s_bibliotheques;
874: while(element_courant != NULL)
875: {
876: element_suivant = (*((struct_liste_chainee *)
877: element_courant)).suivant;
878:
879: element_candidat = (*candidat).s_bibliotheques;
880: while(element_candidat != NULL)
881: {
882: if (((*((struct_bibliotheque *) (*((struct_liste_chainee *)
883: element_courant)).donnee))
884: .descripteur == (*((struct_bibliotheque *)
885: (*((struct_liste_chainee *) element_candidat))
886: .donnee)).descripteur) &&
887: ((*((struct_bibliotheque *)
888: (*((struct_liste_chainee *) element_courant))
889: .donnee)).pid == (*((struct_bibliotheque *)
890: (*((struct_liste_chainee *) element_candidat))
891: .donnee)).pid) && (pthread_equal(
892: (*((struct_bibliotheque *)
893: (*((struct_liste_chainee *) element_courant))
894: .donnee)).tid, (*((struct_bibliotheque *)
895: (*((struct_liste_chainee *) element_candidat))
896: .donnee)).tid) != 0))
897: {
898: break;
899: }
900:
901: element_candidat = (*((struct_liste_chainee *)
902: element_candidat)).suivant;
903: }
904:
905: if (element_candidat == NULL)
906: {
907: dlclose((*((struct_bibliotheque *)
908: (*((struct_liste_chainee *) element_courant))
909: .donnee)).descripteur);
910: }
911:
912: free((*((struct_bibliotheque *)
913: (*((struct_liste_chainee *)
914: element_courant)).donnee)).nom);
915: free((*((struct_liste_chainee *) element_courant)).donnee);
916: free(element_courant);
917:
918: element_courant = element_suivant;
919: }
920:
921: element_courant = (*s_etat_processus).l_base_pile_last;
922: while(element_courant != NULL)
923: {
924: element_suivant = (*((struct_liste_chainee *)
925: element_courant)).suivant;
926:
927: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
928: element_courant)).donnee).mutex));
929: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
930: element_courant)).donnee).mutex));
931: liberation(s_etat_processus,
932: (*((struct_liste_chainee *) element_courant)).donnee);
933: free(element_courant);
934:
935: element_courant = element_suivant;
936: }
937:
938: element_courant = (*s_etat_processus).l_base_pile_systeme;
939: while(element_courant != NULL)
940: {
941: element_suivant = (*((struct_liste_pile_systeme *)
942: element_courant)).suivant;
943:
944: if ((*((struct_liste_pile_systeme *)
945: element_courant)).indice_boucle != NULL)
946: {
947: pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
948: element_courant)).indice_boucle).mutex));
949: pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
950: element_courant)).indice_boucle).mutex));
951: }
952:
953: liberation(s_etat_processus,
954: (*((struct_liste_pile_systeme *)
955: element_courant)).indice_boucle);
956:
957: if ((*((struct_liste_pile_systeme *)
958: element_courant)).limite_indice_boucle != NULL)
959: {
960: pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
961: element_courant)).limite_indice_boucle).mutex));
962: pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
963: element_courant)).limite_indice_boucle).mutex));
964: }
965:
966: liberation(s_etat_processus,
967: (*((struct_liste_pile_systeme *)
968: element_courant)).limite_indice_boucle);
969:
970: if ((*((struct_liste_pile_systeme *)
971: element_courant)).objet_de_test != NULL)
972: {
973: pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *)
974: element_courant)).objet_de_test).mutex));
975: pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *)
976: element_courant)).objet_de_test).mutex));
977: }
978:
979: liberation(s_etat_processus,
980: (*((struct_liste_pile_systeme *)
981: element_courant)).objet_de_test);
982:
983: if ((*((struct_liste_pile_systeme *)
984: element_courant)).nom_variable != NULL)
985: {
986: free((*((struct_liste_pile_systeme *)
987: element_courant)).nom_variable);
988: }
989:
990: free(element_courant);
991:
992: element_courant = element_suivant;
993: }
994:
995: element_courant = (*s_etat_processus).s_fichiers;
996: while(element_courant != NULL)
997: {
998: element_suivant = (*((struct_liste_chainee *)
999: element_courant)).suivant;
1000:
1001: element_candidat = (*candidat).s_fichiers;
1002: while(element_candidat != NULL)
1003: {
1004: if (((*((struct_descripteur_fichier *)
1005: (*((struct_liste_chainee *) element_courant))
1006: .donnee)).pid ==
1007: (*((struct_descripteur_fichier *)
1008: (*((struct_liste_chainee *) element_candidat))
1009: .donnee)).pid) && (pthread_equal(
1010: (*((struct_descripteur_fichier *)
1011: (*((struct_liste_chainee *) element_courant))
1012: .donnee)).tid, (*((struct_descripteur_fichier *)
1013: (*((struct_liste_chainee *) element_candidat))
1014: .donnee)).tid) != 0))
1015: {
1016: if ((*((struct_descripteur_fichier *)
1017: (*((struct_liste_chainee *) element_courant))
1018: .donnee)).type ==
1019: (*((struct_descripteur_fichier *)
1020: (*((struct_liste_chainee *) element_candidat))
1021: .donnee)).type)
1022: {
1023: if ((*((struct_descripteur_fichier *)
1024: (*((struct_liste_chainee *)
1025: element_candidat)).donnee)).type == 'C')
1026: {
1027: if ((*((struct_descripteur_fichier *)
1028: (*((struct_liste_chainee *)
1029: element_courant)).donnee))
1030: .descripteur_c ==
1031: (*((struct_descripteur_fichier *)
1032: (*((struct_liste_chainee *)
1033: element_candidat)).donnee))
1034: .descripteur_c)
1035: {
1036: break;
1037: }
1038: }
1039: else
1040: {
1041: if (((*((struct_descripteur_fichier *)
1042: (*((struct_liste_chainee *)
1043: element_courant)).donnee))
1044: .descripteur_sqlite ==
1045: (*((struct_descripteur_fichier *)
1046: (*((struct_liste_chainee *)
1047: element_candidat)).donnee))
1048: .descripteur_sqlite) &&
1049: ((*((struct_descripteur_fichier *)
1050: (*((struct_liste_chainee *)
1051: element_courant)).donnee))
1052: .descripteur_c ==
1053: (*((struct_descripteur_fichier *)
1054: (*((struct_liste_chainee *)
1055: element_candidat)).donnee))
1056: .descripteur_c))
1057: {
1058: break;
1059: }
1060: }
1061: }
1062: }
1063:
1064: element_candidat = (*((struct_liste_chainee *)
1065: element_candidat)).suivant;
1066: }
1067:
1068: if (element_candidat == NULL)
1069: {
1070: fclose((*((struct_descripteur_fichier *)
1071: (*((struct_liste_chainee *) element_courant))
1072: .donnee)).descripteur_c);
1073:
1074: if ((*((struct_descripteur_fichier *)
1075: (*((struct_liste_chainee *) element_courant))
1076: .donnee)).type != 'C')
1077: {
1078: sqlite3_close((*((struct_descripteur_fichier *)
1079: (*((struct_liste_chainee *) element_courant))
1080: .donnee)).descripteur_sqlite);
1081: }
1082: }
1083:
1084: free((*((struct_descripteur_fichier *)
1085: (*((struct_liste_chainee *)
1086: element_courant)).donnee)).nom);
1087: free((struct_descripteur_fichier *)
1088: (*((struct_liste_chainee *)
1089: element_courant)).donnee);
1090: free(element_courant);
1091:
1092: element_courant = element_suivant;
1093: }
1094:
1095: element_courant = (*s_etat_processus).s_sockets;
1096: while(element_courant != NULL)
1097: {
1098: element_suivant = (*((struct_liste_chainee *)
1099: element_courant)).suivant;
1100:
1101: element_candidat = (*candidat).s_sockets;
1102: while(element_candidat != NULL)
1103: {
1104: if (((*((struct_socket *)
1105: (*((struct_liste_chainee *) element_courant))
1106: .donnee)).socket == (*((struct_socket *)
1107: (*((struct_liste_chainee *) element_candidat))
1108: .donnee)).socket) &&
1109: ((*((struct_socket *)
1110: (*((struct_liste_chainee *) element_courant))
1111: .donnee)).pid == (*((struct_socket *)
1112: (*((struct_liste_chainee *) element_candidat))
1113: .donnee)).pid) && (pthread_equal(
1114: (*((struct_socket *)
1115: (*((struct_liste_chainee *) element_courant))
1116: .donnee)).tid, (*((struct_socket *)
1117: (*((struct_liste_chainee *) element_candidat))
1118: .donnee)).tid) != 0))
1119: {
1120: break;
1121: }
1122:
1123: element_candidat = (*((struct_liste_chainee *)
1124: element_candidat)).suivant;
1125: }
1126:
1127: if (element_candidat == NULL)
1128: {
1129: if ((*((struct_socket *) (*((struct_liste_chainee *)
1130: element_courant)).donnee)).socket_connectee
1131: == d_vrai)
1132: {
1133: shutdown((*((struct_socket *)
1134: (*((struct_liste_chainee *) element_courant))
1135: .donnee)).socket, SHUT_RDWR);
1136: }
1137:
1138: close((*((struct_socket *)
1139: (*((struct_liste_chainee *) element_courant))
1140: .donnee)).socket);
1141: }
1142:
1143: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
1144: element_courant)).donnee).mutex));
1145: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
1146: element_courant)).donnee).mutex));
1147:
1148: liberation(s_etat_processus,
1149: (*((struct_liste_chainee *)
1150: element_courant)).donnee);
1151: free(element_courant);
1152:
1153: element_courant = element_suivant;
1154: }
1155:
1156: element_courant = (*s_etat_processus).s_connecteurs_sql;
1157: while(element_courant != NULL)
1158: {
1159: element_suivant = (*((struct_liste_chainee *)
1160: element_courant)).suivant;
1161:
1162: element_candidat = (*candidat).s_connecteurs_sql;
1163: while(element_candidat != NULL)
1164: {
1165: if (((
1166: #ifdef MYSQL_SUPPORT
1167: ((*((struct_connecteur_sql *)
1168: (*((struct_liste_chainee *) element_courant))
1169: .donnee)).descripteur.mysql ==
1170: (*((struct_connecteur_sql *)
1171: (*((struct_liste_chainee *) element_candidat))
1172: .donnee)).descripteur.mysql)
1173: &&
1174: (strcmp((*((struct_connecteur_sql *)
1175: (*((struct_liste_chainee *) element_courant))
1176: .donnee)).type, "MYSQL") == 0)
1177: &&
1178: (strcmp((*((struct_connecteur_sql *)
1179: (*((struct_liste_chainee *) element_candidat))
1180: .donnee)).type, "MYSQL") == 0)
1181: #else
1182: 0
1183: #endif
1184: ) || (
1185: #ifdef POSTGRESQL_SUPPORT
1186: ((*((struct_connecteur_sql *)
1187: (*((struct_liste_chainee *) element_courant))
1188: .donnee)).descripteur.postgresql ==
1189: (*((struct_connecteur_sql *)
1190: (*((struct_liste_chainee *) element_candidat))
1191: .donnee)).descripteur.postgresql)
1192: &&
1193: (strcmp((*((struct_connecteur_sql *)
1194: (*((struct_liste_chainee *) element_courant))
1195: .donnee)).type, "POSTGRESQL") == 0)
1196: &&
1197: (strcmp((*((struct_connecteur_sql *)
1198: (*((struct_liste_chainee *) element_candidat))
1199: .donnee)).type, "POSTGRESQL") == 0)
1200: #else
1201: 0
1202: #endif
1203: )) &&
1204: ((*((struct_connecteur_sql *)
1205: (*((struct_liste_chainee *) element_courant))
1206: .donnee)).pid == (*((struct_connecteur_sql *)
1207: (*((struct_liste_chainee *) element_candidat))
1208: .donnee)).pid) && (pthread_equal(
1209: (*((struct_connecteur_sql *)
1210: (*((struct_liste_chainee *) element_courant))
1211: .donnee)).tid, (*((struct_connecteur_sql *)
1212: (*((struct_liste_chainee *) element_candidat))
1213: .donnee)).tid) != 0))
1214: {
1215: break;
1216: }
1217:
1218: element_candidat = (*((struct_liste_chainee *)
1219: element_candidat)).suivant;
1220: }
1221:
1222: if (element_candidat == NULL)
1223: {
1224: sqlclose((*((struct_liste_chainee *) element_courant))
1225: .donnee);
1226: }
1227:
1228: pthread_mutex_trylock(&((*(*((struct_liste_chainee *)
1229: element_courant)).donnee).mutex));
1230: pthread_mutex_unlock(&((*(*((struct_liste_chainee *)
1231: element_courant)).donnee).mutex));
1232:
1233: liberation(s_etat_processus, (*((struct_liste_chainee *)
1234: element_courant)).donnee);
1235: free(element_courant);
1236:
1237: element_courant = element_suivant;
1238: }
1239:
1240: element_courant = (*s_etat_processus).s_marques;
1241: while(element_courant != NULL)
1242: {
1243: free((*((struct_marque *) element_courant)).label);
1244: free((*((struct_marque *) element_courant)).position);
1245: element_suivant = (*((struct_marque *) element_courant))
1246: .suivant;
1247: free(element_courant);
1248: element_courant = element_suivant;
1249: }
1250:
1251: liberation_allocateur(s_etat_processus);
1252:
1253: # ifndef SEMAPHORES_NOMMES
1254: sem_post(&((*s_etat_processus).semaphore_fork));
1255: sem_destroy(&((*s_etat_processus).semaphore_fork));
1256: # else
1257: sem_post((*s_etat_processus).semaphore_fork);
1258: sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork);
1259: # endif
1260:
1261: free(s_etat_processus);
1262:
1263: s_etat_processus = candidat;
1264: }
1265:
1266: l_element_suivant = (*l_element_courant).suivant;
1267:
1268: free((struct_thread *) (*l_element_courant).donnee);
1269: free((struct_liste_chainee *) l_element_courant);
1270:
1271: l_element_courant = l_element_suivant;
1272: }
1273:
1274: liste_threads = NULL;
1275:
1276: l_element_courant = liste_threads_surveillance;
1277:
1278: while(l_element_courant != NULL)
1279: {
1280: s_argument_thread = (struct_descripteur_thread *)
1281: (*l_element_courant).donnee;
1282:
1283: close((*s_argument_thread).pipe_objets[0]);
1284: close((*s_argument_thread).pipe_acquittement[1]);
1285: close((*s_argument_thread).pipe_injections[1]);
1286: close((*s_argument_thread).pipe_nombre_injections[1]);
1287: close((*s_argument_thread).pipe_nombre_objets_attente[0]);
1288: close((*s_argument_thread).pipe_interruptions[0]);
1289: close((*s_argument_thread).pipe_nombre_interruptions_attente[0]);
1290:
1291: if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0)
1292: {
1293: (*s_etat_processus).erreur_systeme = d_es_processus;
1294: return;
1295: }
1296:
1297: (*s_argument_thread).nombre_references--;
1298:
1299: BUG((*s_argument_thread).nombre_references < 0,
1300: printf("(*s_argument_thread).nombre_references = %d\n",
1301: (int) (*s_argument_thread).nombre_references));
1302:
1303: if ((*s_argument_thread).nombre_references == 0)
1304: {
1305: if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)
1306: {
1307: (*s_etat_processus).erreur_systeme = d_es_processus;
1308: return;
1309: }
1310:
1311: pthread_mutex_destroy(&((*s_argument_thread).mutex));
1312: free(s_argument_thread);
1313: }
1314: else
1315: {
1316: if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0)
1317: {
1318: (*s_etat_processus).erreur_systeme = d_es_processus;
1319: return;
1320: }
1321: }
1322:
1323: l_element_suivant = (*l_element_courant).suivant;
1324: free((struct_liste_chainee *) l_element_courant);
1325: l_element_courant = l_element_suivant;
1326: }
1327:
1328: liste_threads_surveillance = NULL;
1329:
1330: # ifndef SEMAPHORES_NOMMES
1331: if (sem_post(&semaphore_liste_threads) != 0)
1332: # else
1333: if (sem_post(semaphore_liste_threads) != 0)
1334: # endif
1335: {
1336: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1337: (*s_etat_processus).erreur_systeme = d_es_processus;
1338: return;
1339: }
1340:
1341: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1342: sigpending(&set);
1343: return;
1344: }
1345:
1346: static struct_processus *
1347: recherche_thread(pid_t pid, pthread_t tid)
1348: {
1349: volatile struct_liste_chainee_volatile *l_element_courant;
1350:
1351: struct_processus *s_etat_processus;
1352:
1353: l_element_courant = liste_threads;
1354:
1355: while(l_element_courant != NULL)
1356: {
1357: if ((pthread_equal((*((struct_thread *) (*l_element_courant).donnee))
1358: .tid, tid) != 0) && ((*((struct_thread *)
1359: (*l_element_courant).donnee)).pid == pid))
1360: {
1361: break;
1362: }
1363:
1364: l_element_courant = (*l_element_courant).suivant;
1365: }
1366:
1367: if (l_element_courant == NULL)
1368: {
1369: /*
1370: * Le processus n'existe plus. On ne distribue aucun signal.
1371: */
1372:
1373: return(NULL);
1374: }
1375:
1376: s_etat_processus = (*((struct_thread *)
1377: (*l_element_courant).donnee)).s_etat_processus;
1378:
1379: return(s_etat_processus);
1380: }
1381:
1382: static logical1
1383: recherche_thread_principal(pid_t pid, pthread_t *thread)
1384: {
1385: volatile struct_liste_chainee_volatile *l_element_courant;
1386:
1387: l_element_courant = liste_threads;
1388:
1389: while(l_element_courant != NULL)
1390: {
1391: if (((*((struct_thread *) (*l_element_courant).donnee)).thread_principal
1392: == d_vrai) && ((*((struct_thread *)
1393: (*l_element_courant).donnee)).pid == pid))
1394: {
1395: break;
1396: }
1397:
1398: l_element_courant = (*l_element_courant).suivant;
1399: }
1400:
1401: if (l_element_courant == NULL)
1402: {
1403: /*
1404: * Le processus n'existe plus. On ne distribue aucun signal.
1405: */
1406:
1407: return(d_faux);
1408: }
1409:
1410: (*thread) = (*((struct_thread *) (*l_element_courant).donnee)).tid;
1411:
1412: return(d_vrai);
1413: }
1414:
1415:
1416: /*
1417: ================================================================================
1418: Procédures de gestion des signaux d'interruption
1419: ================================================================================
1420: Entrée : variable globale
1421: --------------------------------------------------------------------------------
1422: Sortie : variable globale modifiée
1423: --------------------------------------------------------------------------------
1424: Effets de bord : néant
1425: ================================================================================
1426: */
1427:
1428: // Les routines suivantes sont uniquement appelées depuis les gestionnaires
1429: // des signaux asynchrones. Elles de doivent pas bloquer dans le cas où
1430: // les sémaphores sont déjà bloqués par un gestionnaire de signal.
1431:
1432: static inline void
1433: verrouillage_gestionnaire_signaux()
1434: {
1435: int semaphore;
1436:
1437: sigset_t oldset;
1438: sigset_t set;
1439:
1440: sem_t *sem;
1441:
1442: if ((sem = pthread_getspecific(semaphore_fork_processus_courant))
1443: != NULL)
1444: {
1445: if (sem_post(sem) != 0)
1446: {
1447: BUG(1, uprintf("Lock error !\n"));
1448: return;
1449: }
1450: }
1451:
1452: // Il faut respecteur l'atomicité des deux opérations suivantes !
1453:
1454: sigfillset(&set);
1455: pthread_sigmask(SIG_BLOCK, &set, &oldset);
1456:
1457: # ifndef SEMAPHORES_NOMMES
1458: while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)
1459: # else
1460: while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)
1461: # endif
1462: {
1463: if (errno != EINTR)
1464: {
1465: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1466: BUG(1, uprintf("Unlock error !\n"));
1467: return;
1468: }
1469: }
1470:
1471: # ifndef SEMAPHORES_NOMMES
1472: if (sem_post(&semaphore_gestionnaires_signaux) == -1)
1473: # else
1474: if (sem_post(semaphore_gestionnaires_signaux) == -1)
1475: # endif
1476: {
1477: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1478: BUG(1, uprintf("Lock error !\n"));
1479: return;
1480: }
1481:
1482: # ifndef SEMAPHORES_NOMMES
1483: if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)
1484: # else
1485: if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)
1486: # endif
1487: {
1488: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1489: BUG(1, uprintf("Lock error !\n"));
1490: return;
1491: }
1492:
1493: # ifndef SEMAPHORES_NOMMES
1494: if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0)
1495: # else
1496: if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0)
1497: # endif
1498: {
1499: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1500: BUG(1, uprintf("Unlock error !\n"));
1501: return;
1502: }
1503:
1504: if (semaphore == 1)
1505: {
1506: // Le semaphore ne peut être pris par le thread qui a appelé
1507: // le gestionnaire de signal car le signal est bloqué par ce thread
1508: // dans les zones critiques. Ce sémaphore ne peut donc être bloqué que
1509: // par un thread concurrent. On essaye donc de le bloquer jusqu'à
1510: // ce que ce soit possible.
1511:
1512: # ifndef SEMAPHORES_NOMMES
1513: while(sem_trywait(&semaphore_liste_threads) == -1)
1514: # else
1515: while(sem_trywait(semaphore_liste_threads) == -1)
1516: # endif
1517: {
1518: if ((errno != EINTR) && (errno != EAGAIN))
1519: {
1520: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1521:
1522: while(sem_wait(sem) == -1)
1523: {
1524: if (errno != EINTR)
1525: {
1526: BUG(1, uprintf("Lock error !\n"));
1527: return;
1528: }
1529: }
1530:
1531: BUG(1, uprintf("Lock error !\n"));
1532: return;
1533: }
1534:
1535: sched_yield();
1536: }
1537: }
1538:
1539: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1540: sigpending(&set);
1541:
1542: return;
1543: }
1544:
1545: static inline void
1546: deverrouillage_gestionnaire_signaux()
1547: {
1548: int semaphore;
1549:
1550: sem_t *sem;
1551:
1552: sigset_t oldset;
1553: sigset_t set;
1554:
1555: // Il faut respecteur l'atomicité des deux opérations suivantes !
1556:
1557: sigfillset(&set);
1558: pthread_sigmask(SIG_BLOCK, &set, &oldset);
1559:
1560: # ifndef SEMAPHORES_NOMMES
1561: while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1)
1562: # else
1563: while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1)
1564: # endif
1565: {
1566: if (errno != EINTR)
1567: {
1568: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1569: BUG(1, uprintf("Unlock error !\n"));
1570: return;
1571: }
1572: }
1573:
1574: # ifndef SEMAPHORES_NOMMES
1575: if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0)
1576: # else
1577: if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0)
1578: # endif
1579: {
1580: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1581: BUG(1, uprintf("Unlock error !\n"));
1582: return;
1583: }
1584:
1585: # ifndef SEMAPHORES_NOMMES
1586: while(sem_wait(&semaphore_gestionnaires_signaux) == -1)
1587: # else
1588: while(sem_wait(semaphore_gestionnaires_signaux) == -1)
1589: # endif
1590: {
1591: if (errno != EINTR)
1592: {
1593: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1594: BUG(1, uprintf("Unlock error !\n"));
1595: return;
1596: }
1597: }
1598:
1599: # ifndef SEMAPHORES_NOMMES
1600: if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0)
1601: # else
1602: if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0)
1603: # endif
1604: {
1605: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1606: BUG(1, uprintf("Unlock error !\n"));
1607: return;
1608: }
1609:
1610: if ((sem = pthread_getspecific(semaphore_fork_processus_courant))
1611: != NULL)
1612: {
1613: while(sem_wait(sem) == -1)
1614: {
1615: if (errno != EINTR)
1616: {
1617: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1618: BUG(1, uprintf("Unlock error !\n"));
1619: return;
1620: }
1621: }
1622: }
1623:
1624: if (semaphore == 1)
1625: {
1626: # ifndef SEMAPHORES_NOMMES
1627: if (sem_post(&semaphore_liste_threads) != 0)
1628: # else
1629: if (sem_post(semaphore_liste_threads) != 0)
1630: # endif
1631: {
1632: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1633:
1634: BUG(1, uprintf("Unlock error !\n"));
1635: return;
1636: }
1637: }
1638:
1639: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1640: sigpending(&set);
1641:
1642: return;
1643: }
1644:
1645: void
1646: interruption1(int signal, siginfo_t *siginfo, void *context)
1647: {
1648: pthread_t thread;
1649:
1650: struct_processus *s_etat_processus;
1651:
1652: volatile sig_atomic_t exclusion = 0;
1653:
1654: verrouillage_gestionnaire_signaux();
1655:
1656: switch(signal)
1657: {
1658: case SIGALRM :
1659: {
1660: if ((*siginfo).si_pid == getpid())
1661: {
1662: if ((s_etat_processus = recherche_thread(getpid(),
1663: pthread_self())) == NULL)
1664: {
1665: deverrouillage_gestionnaire_signaux();
1666: return;
1667: }
1668:
1669: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1670: {
1671: printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(),
1672: (unsigned long long) pthread_self());
1673: fflush(stdout);
1674: }
1675:
1676: if ((*s_etat_processus).pid_processus_pere != getpid())
1677: {
1678: kill((*s_etat_processus).pid_processus_pere, signal);
1679: }
1680: else
1681: {
1682: (*s_etat_processus).var_volatile_alarme = -1;
1683: (*s_etat_processus).var_volatile_requete_arret = -1;
1684: }
1685: }
1686: else
1687: {
1688: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
1689: {
1690: pthread_kill(thread, signal);
1691: }
1692: }
1693:
1694: break;
1695: }
1696:
1697: case SIGINT :
1698: {
1699: /*
1700: * Une vieille spécification POSIX permet au pointeur siginfo
1701: * d'être nul dans le cas d'un ^C envoyé depuis le clavier.
1702: * Solaris suit en particulier cette spécification.
1703: */
1704:
1705: if (siginfo == NULL)
1706: {
1707: kill(getpid(), signal);
1708: }
1709: else if ((*siginfo).si_pid == getpid())
1710: {
1711: if ((s_etat_processus = recherche_thread(getpid(),
1712: pthread_self())) == NULL)
1713: {
1714: deverrouillage_gestionnaire_signaux();
1715: return;
1716: }
1717:
1718: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1719: {
1720: printf("[%d] SIGINT (thread %llu)\n", (int) getpid(),
1721: (unsigned long long) pthread_self());
1722: fflush(stdout);
1723: }
1724:
1725: if ((*s_etat_processus).pid_processus_pere != getpid())
1726: {
1727: kill((*s_etat_processus).pid_processus_pere, signal);
1728: }
1729: else
1730: {
1731: (*s_etat_processus).var_volatile_traitement_sigint = -1;
1732:
1733: while(exclusion == 1);
1734: exclusion = 1;
1735:
1736: if ((*s_etat_processus).var_volatile_requete_arret == -1)
1737: {
1738: deverrouillage_gestionnaire_signaux();
1739: exclusion = 0;
1740: return;
1741: }
1742:
1743: if (strncmp(getenv("LANG"), "fr", 2) == 0)
1744: {
1745: printf("+++Interruption\n");
1746: }
1747: else
1748: {
1749: printf("+++Interrupt\n");
1750: }
1751:
1752: fflush(stdout);
1753:
1754: (*s_etat_processus).var_volatile_requete_arret = -1;
1755: (*s_etat_processus).var_volatile_alarme = -1;
1756:
1757: exclusion = 0;
1758: }
1759: }
1760: else
1761: {
1762: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
1763: {
1764: pthread_kill(thread, signal);
1765: }
1766: }
1767:
1768: break;
1769: }
1770:
1771: default :
1772: {
1773: BUG(1, uprintf("[%d] Unknown signal %d in this context\n",
1774: (int) getpid(), signal));
1775: break;
1776: }
1777: }
1778:
1779: deverrouillage_gestionnaire_signaux();
1780: return;
1781: }
1782:
1783: void
1784: interruption2(int signal, siginfo_t *siginfo, void *context)
1785: {
1786: pthread_t thread;
1787: struct_processus *s_etat_processus;
1788:
1789: verrouillage_gestionnaire_signaux();
1790:
1791: if (siginfo == NULL)
1792: {
1793: /*
1794: * Le signal SIGFSTP provient de la mort du processus de contrôle.
1795: * Sous certains systèmes (Linux...), la mort du terminal de contrôle
1796: * se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres
1797: * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo
1798: * non initialisée (pointeur NULL) issue de TERMIO.
1799: */
1800:
1801: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
1802: {
1803: pthread_kill(thread, SIGHUP);
1804: deverrouillage_gestionnaire_signaux();
1805: return;
1806: }
1807: }
1808: else if ((*siginfo).si_pid == getpid())
1809: {
1810: if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
1811: == NULL)
1812: {
1813: deverrouillage_gestionnaire_signaux();
1814: return;
1815: }
1816:
1817: /*
1818: * 0 => fonctionnement normal
1819: * -1 => requête
1820: * 1 => requête acceptée en attente de traitement
1821: */
1822:
1823: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1824: {
1825: printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(),
1826: (unsigned long long) pthread_self());
1827: fflush(stdout);
1828: }
1829:
1830: if ((*s_etat_processus).var_volatile_processus_pere == 0)
1831: {
1832: kill((*s_etat_processus).pid_processus_pere, signal);
1833: }
1834: else
1835: {
1836: (*s_etat_processus).var_volatile_requete_arret2 = -1;
1837: }
1838: }
1839: else
1840: {
1841: // Envoi d'un signal au thread maître du groupe.
1842:
1843: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
1844: {
1845: pthread_kill(thread, SIGTSTP);
1846: deverrouillage_gestionnaire_signaux();
1847: return;
1848: }
1849: }
1850:
1851: deverrouillage_gestionnaire_signaux();
1852: return;
1853: }
1854:
1855: void
1856: interruption3(int signal, siginfo_t *siginfo, void *context)
1857: {
1858: struct_processus *s_etat_processus;
1859:
1860: static int compteur = 0;
1861:
1862: verrouillage_gestionnaire_signaux();
1863:
1864: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
1865: {
1866: deverrouillage_gestionnaire_signaux();
1867: return;
1868: }
1869:
1870: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1871: {
1872: printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(),
1873: (unsigned long long) pthread_self());
1874: fflush(stdout);
1875: }
1876:
1877: if ((*s_etat_processus).var_volatile_recursivite == -1)
1878: {
1879: // Segfault dans un appel de fonction récursive
1880: deverrouillage_gestionnaire_signaux();
1881: longjmp(contexte, -1);
1882: }
1883: else
1884: {
1885: // Segfault dans une routine interne
1886: if (strncmp(getenv("LANG"), "fr", 2) == 0)
1887: {
1888: printf("+++Système : Violation d'accès (dépassement de pile)\n");
1889: }
1890: else
1891: {
1892: printf("+++System : Access violation (stack overflow)\n");
1893: }
1894:
1895: fflush(stdout);
1896:
1897: compteur++;
1898:
1899: if (compteur > 1)
1900: {
1901: deverrouillage_gestionnaire_signaux();
1902: exit(EXIT_FAILURE);
1903: }
1904: else
1905: {
1906: deverrouillage_gestionnaire_signaux();
1907: longjmp(contexte_initial, -1);
1908: }
1909: }
1910:
1911: deverrouillage_gestionnaire_signaux();
1912: return;
1913: }
1914:
1915: void
1916: interruption4(int signal, siginfo_t *siginfo, void *context)
1917: {
1918: struct_processus *s_etat_processus;
1919:
1920: verrouillage_gestionnaire_signaux();
1921:
1922: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
1923: {
1924: deverrouillage_gestionnaire_signaux();
1925: return;
1926: }
1927:
1928: /*
1929: * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND)
1930: */
1931:
1932: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1933: {
1934: printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(),
1935: (unsigned long long) pthread_self());
1936: fflush(stdout);
1937: }
1938:
1939: deverrouillage_gestionnaire_signaux();
1940: return;
1941: }
1942:
1943: void
1944: interruption5(int signal, siginfo_t *siginfo, void *context)
1945: {
1946: pthread_t thread;
1947: struct_processus *s_etat_processus;
1948:
1949: verrouillage_gestionnaire_signaux();
1950:
1951: if ((*siginfo).si_pid == getpid())
1952: {
1953: if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
1954: == NULL)
1955: {
1956: deverrouillage_gestionnaire_signaux();
1957: return;
1958: }
1959:
1960: if (signal == SIGFABORT)
1961: {
1962: (*s_etat_processus).arret_depuis_abort = -1;
1963: }
1964:
1965: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
1966: {
1967: if (signal == SIGFSTOP)
1968: {
1969: printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(),
1970: (unsigned long long) pthread_self());
1971: fflush(stdout);
1972: }
1973: else
1974: {
1975: printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(),
1976: (unsigned long long) pthread_self());
1977: fflush(stdout);
1978: }
1979: }
1980:
1981: /*
1982: * var_globale_traitement_retarde_stop :
1983: * 0 -> traitement immédiat
1984: * 1 -> traitement retardé (aucun signal reçu)
1985: * -1 -> traitement retardé (un ou plusieurs signaux stop reçus)
1986: */
1987:
1988: if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0)
1989: {
1990: (*s_etat_processus).var_volatile_requete_arret = -1;
1991: }
1992: else
1993: {
1994: (*s_etat_processus).var_volatile_traitement_retarde_stop = -1;
1995: }
1996: }
1997: else
1998: {
1999: if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
2000: == NULL)
2001: {
2002: deverrouillage_gestionnaire_signaux();
2003: return;
2004: }
2005:
2006: if (signal == SIGFABORT)
2007: {
2008: (*s_etat_processus).arret_depuis_abort = -1;
2009: }
2010:
2011: // Envoi d'un signal au thread maître du groupe.
2012:
2013: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
2014: {
2015: pthread_kill(thread, signal);
2016: deverrouillage_gestionnaire_signaux();
2017: return;
2018: }
2019: }
2020:
2021: deverrouillage_gestionnaire_signaux();
2022: return;
2023: }
2024:
2025: void
2026: interruption6(int signal, siginfo_t *siginfo, void *context)
2027: {
2028: struct_processus *s_etat_processus;
2029:
2030: verrouillage_gestionnaire_signaux();
2031:
2032: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2033: {
2034: deverrouillage_gestionnaire_signaux();
2035: return;
2036: }
2037:
2038: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2039: {
2040: printf("[%d] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(),
2041: (unsigned long long) pthread_self());
2042: fflush(stdout);
2043: }
2044:
2045: deverrouillage_gestionnaire_signaux();
2046: return;
2047: }
2048:
2049: void
2050: interruption7(int signal, siginfo_t *siginfo, void *context)
2051: {
2052: struct_processus *s_etat_processus;
2053:
2054: verrouillage_gestionnaire_signaux();
2055:
2056: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2057: {
2058: deverrouillage_gestionnaire_signaux();
2059: return;
2060: }
2061:
2062: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2063: {
2064: printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(),
2065: (unsigned long long) pthread_self());
2066: fflush(stdout);
2067: }
2068:
2069: (*s_etat_processus).var_volatile_requete_arret = -1;
2070: deverrouillage_gestionnaire_signaux();
2071:
2072: BUG(1, printf("[%d] SIGPIPE\n", (int) getpid()));
2073: return;
2074: }
2075:
2076: void
2077: interruption8(int signal, siginfo_t *siginfo, void *context)
2078: {
2079: pthread_t thread;
2080: struct_processus *s_etat_processus;
2081:
2082: verrouillage_gestionnaire_signaux();
2083:
2084: if ((*siginfo).si_pid == getpid())
2085: {
2086: if ((s_etat_processus = recherche_thread(getpid(), pthread_self()))
2087: == NULL)
2088: {
2089: deverrouillage_gestionnaire_signaux();
2090: return;
2091: }
2092:
2093: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2094: {
2095: printf("[%d] SIGURG (thread %llu)\n", (int) getpid(),
2096: (unsigned long long) pthread_self());
2097: fflush(stdout);
2098: }
2099:
2100: (*s_etat_processus).var_volatile_alarme = -1;
2101: (*s_etat_processus).var_volatile_requete_arret = -1;
2102: }
2103: else
2104: {
2105: // Envoi d'un signal au thread maître du groupe.
2106:
2107: if (recherche_thread_principal(getpid(), &thread) == d_vrai)
2108: {
2109: pthread_kill(thread, SIGURG);
2110: deverrouillage_gestionnaire_signaux();
2111: return;
2112: }
2113: }
2114:
2115: deverrouillage_gestionnaire_signaux();
2116: return;
2117: }
2118:
2119: void
2120: interruption9(int signal, siginfo_t *siginfo, void *context)
2121: {
2122: struct_processus *s_etat_processus;
2123:
2124: verrouillage_gestionnaire_signaux();
2125:
2126: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2127: {
2128: deverrouillage_gestionnaire_signaux();
2129: return;
2130: }
2131:
2132: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2133: {
2134: printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(),
2135: (unsigned long long) pthread_self());
2136: fflush(stdout);
2137: }
2138:
2139: pthread_kill((*s_etat_processus).tid_processus_pere, SIGFABORT);
2140: deverrouillage_gestionnaire_signaux();
2141: return;
2142: }
2143:
2144: void
2145: interruption10(int signal, siginfo_t *siginfo, void *context)
2146: {
2147: file *fichier;
2148:
2149: struct_processus *s_etat_processus;
2150:
2151: unsigned char nom[8 + 64 + 1];
2152:
2153: verrouillage_gestionnaire_signaux();
2154:
2155: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2156: {
2157: deverrouillage_gestionnaire_signaux();
2158: return;
2159: }
2160:
2161: snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(),
2162: (unsigned long) pthread_self());
2163:
2164: if ((fichier = fopen(nom, "w+")) != NULL)
2165: {
2166: fclose(fichier);
2167:
2168: freopen(nom, "w", stdout);
2169: freopen(nom, "w", stderr);
2170: }
2171:
2172: freopen("/dev/null", "r", stdin);
2173:
2174: if (((*s_etat_processus).type_debug & d_debug_signaux) != 0)
2175: {
2176: printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(),
2177: (unsigned long long) pthread_self());
2178: fflush(stdout);
2179: }
2180:
2181: deverrouillage_gestionnaire_signaux();
2182: return;
2183: }
2184:
2185: void
2186: traitement_exceptions_gsl(const char *reason, const char *file,
2187: int line, int gsl_errno)
2188: {
2189: struct_processus *s_etat_processus;
2190:
2191: verrouillage_gestionnaire_signaux();
2192:
2193: if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL)
2194: {
2195: deverrouillage_gestionnaire_signaux();
2196: return;
2197: }
2198:
2199: (*s_etat_processus).var_volatile_exception_gsl = gsl_errno;
2200: deverrouillage_gestionnaire_signaux();
2201: return;
2202: }
2203:
2204: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>