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