/* ================================================================================ RPL/2 (R) version 4.0.15 Copyright (C) 1989-2010 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl.conv.h" /* ================================================================================ Procédures de gestion par thread des variables issues des gestionnaires de signaux ================================================================================ Entrée : variable globale -------------------------------------------------------------------------------- Sortie : variable globale modifiée -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ typedef struct thread { pid_t pid; pthread_t tid; logical1 thread_principal; struct_processus *s_etat_processus; } struct_thread; typedef struct liste_chainee_volatile { volatile struct liste_chainee_volatile *suivant; volatile void *donnee; } struct_liste_chainee_volatile; static volatile struct_liste_chainee_volatile *liste_threads = NULL; static volatile struct_liste_chainee_volatile *liste_threads_surveillance = NULL; void modification_pid_thread_pere(struct_processus *s_etat_processus) { // La variable existe toujours et aucun thread concurrent ne peut // la modifier puisque cette routine ne peut être appelée que depuis // DAEMON. (*((struct_thread *) (*liste_threads).donnee)).pid = (*s_etat_processus).pid_processus_pere; return; } void insertion_thread(struct_processus *s_etat_processus, logical1 thread_principal) { sigset_t oldset; sigset_t set; volatile struct_liste_chainee_volatile *l_nouvel_objet; sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile))) == NULL) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*l_nouvel_objet).donnee = malloc(sizeof(struct_thread))) == NULL) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } (*((struct_thread *) (*l_nouvel_objet).donnee)).pid = getpid(); (*((struct_thread *) (*l_nouvel_objet).donnee)).tid = pthread_self(); (*((struct_thread *) (*l_nouvel_objet).donnee)).thread_principal = thread_principal; (*((struct_thread *) (*l_nouvel_objet).donnee)).s_etat_processus = s_etat_processus; # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } (*l_nouvel_objet).suivant = liste_threads; liste_threads = l_nouvel_objet; # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } void insertion_thread_surveillance(struct_processus *s_etat_processus, struct_descripteur_thread *s_argument_thread) { sigset_t oldset; sigset_t set; volatile struct_liste_chainee_volatile *l_nouvel_objet; sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); if ((l_nouvel_objet = malloc(sizeof(struct_liste_chainee_volatile))) == NULL) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } (*l_nouvel_objet).suivant = liste_threads_surveillance; (*l_nouvel_objet).donnee = (void *) s_argument_thread; liste_threads_surveillance = l_nouvel_objet; # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } void retrait_thread(struct_processus *s_etat_processus) { sigset_t oldset; sigset_t set; volatile struct_liste_chainee_volatile *l_element_precedent; volatile struct_liste_chainee_volatile *l_element_courant; sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } l_element_precedent = NULL; l_element_courant = liste_threads; while(l_element_courant != NULL) { if (((*((struct_thread *) (*l_element_courant).donnee)).pid == getpid()) && (pthread_equal((*((struct_thread *) (*l_element_courant).donnee)).tid, pthread_self()) != 0)) { break; } l_element_precedent = l_element_courant; l_element_courant = (*l_element_courant).suivant; } if (l_element_courant == NULL) { # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (l_element_precedent == NULL) { liste_threads = (*l_element_courant).suivant; } else { (*l_element_precedent).suivant = (*l_element_courant).suivant; } if (pthread_setspecific(semaphore_fork_processus_courant, NULL) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } free((void *) (*l_element_courant).donnee); free((struct_liste_chainee_volatile *) l_element_courant); pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } void retrait_thread_surveillance(struct_processus *s_etat_processus, struct_descripteur_thread *s_argument_thread) { sigset_t set; sigset_t oldset; volatile struct_liste_chainee_volatile *l_element_precedent; volatile struct_liste_chainee_volatile *l_element_courant; sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } l_element_precedent = NULL; l_element_courant = liste_threads_surveillance; while(l_element_courant != NULL) { if ((*l_element_courant).donnee == (void *) s_argument_thread) { break; } l_element_precedent = l_element_courant; l_element_courant = (*l_element_courant).suivant; } if (l_element_courant == NULL) { # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } // l_element_courant->donnee n'est pas bonne lorsque ça part en vrille. if (l_element_precedent == NULL) { liste_threads_surveillance = (*l_element_courant).suivant; } else { (*l_element_precedent).suivant = (*l_element_courant).suivant; } if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0) { # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } (*s_argument_thread).nombre_references--; BUG((*s_argument_thread).nombre_references < 0, printf("(*s_argument_thread).nombre_references = %d\n", (int) (*s_argument_thread).nombre_references)); if ((*s_argument_thread).nombre_references == 0) { if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0) { # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } pthread_mutex_destroy(&((*s_argument_thread).mutex)); free(s_argument_thread); } else { if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0) { # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_liste_threads); # else sem_post(semaphore_liste_threads); # endif pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); (*s_etat_processus).erreur_systeme = d_es_processus; return; } free((struct_liste_chainee_volatile *) l_element_courant); pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } void verrouillage_threads_concurrents(struct_processus *s_etat_processus) { volatile struct_liste_chainee_volatile *l_element_courant; # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } l_element_courant = liste_threads; while(l_element_courant != NULL) { if (((*((struct_thread *) (*l_element_courant).donnee)).pid == getpid()) && (pthread_equal((*((struct_thread *) (*l_element_courant).donnee)).tid, pthread_self()) == 0)) { # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*(*((struct_thread *) (*l_element_courant) .donnee)).s_etat_processus).semaphore_fork)) == -1) # else while(sem_wait((*(*((struct_thread *) (*l_element_courant) .donnee)).s_etat_processus).semaphore_fork) == -1) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } } l_element_courant = (*l_element_courant).suivant; } return; } void deverrouillage_threads_concurrents(struct_processus *s_etat_processus) { volatile struct_liste_chainee_volatile *l_element_courant; l_element_courant = liste_threads; while(l_element_courant != NULL) { if (((*((struct_thread *) (*l_element_courant).donnee)).pid == getpid()) && (pthread_equal((*((struct_thread *) (*l_element_courant).donnee)).tid, pthread_self()) == 0)) { # ifndef SEMAPHORES_NOMMES if (sem_post(&((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus) .semaphore_fork)) != 0) # else if (sem_post((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus) .semaphore_fork) != 0) # endif { # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } # else if (sem_post(semaphore_liste_threads) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } # endif (*s_etat_processus).erreur_systeme = d_es_processus; return; } } l_element_courant = (*l_element_courant).suivant; } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return; } return; } void liberation_threads(struct_processus *s_etat_processus) { logical1 suppression_variables_partagees; sigset_t oldset; sigset_t set; struct_descripteur_thread *s_argument_thread; struct_processus *candidat; unsigned long i; void *element_candidat; void *element_courant; void *element_suivant; volatile struct_liste_chainee_volatile *l_element_courant; volatile struct_liste_chainee_volatile *l_element_suivant; sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_liste_threads) == -1) # else while(sem_wait(semaphore_liste_threads) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); (*s_etat_processus).erreur_systeme = d_es_processus; return; } } l_element_courant = liste_threads; suppression_variables_partagees = d_faux; while(l_element_courant != NULL) { if ((*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus != s_etat_processus) { candidat = s_etat_processus; s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus; free((*s_etat_processus).localisation); // (*s_etat_processus).instruction_courante peut pointer sur // n'importe quoi (une instruction courante ou un champ d'une // structure objet). On ne le libère pas quitte à avoir une // petite fuite mémoire dans le processus fils. if ((*s_etat_processus).instruction_courante != NULL) { //free((*s_etat_processus).instruction_courante); } close((*s_etat_processus).pipe_acquittement); close((*s_etat_processus).pipe_donnees); close((*s_etat_processus).pipe_injections); close((*s_etat_processus).pipe_nombre_injections); close((*s_etat_processus).pipe_interruptions); close((*s_etat_processus).pipe_nombre_objets_attente); close((*s_etat_processus).pipe_nombre_interruptions_attente); liberation(s_etat_processus, (*s_etat_processus).at_exit); if ((*s_etat_processus).nom_fichier_impression != NULL) { free((*s_etat_processus).nom_fichier_impression); } while((*s_etat_processus).fichiers_graphiques != NULL) { free((*(*s_etat_processus).fichiers_graphiques).nom); if ((*(*s_etat_processus).fichiers_graphiques).legende != NULL) { free((*(*s_etat_processus).fichiers_graphiques).legende); } element_courant = (*s_etat_processus).fichiers_graphiques; (*s_etat_processus).fichiers_graphiques = (*(*s_etat_processus).fichiers_graphiques).suivant; free(element_courant); } if ((*s_etat_processus).entree_standard != NULL) { pclose((*s_etat_processus).entree_standard); } if ((*s_etat_processus).generateur_aleatoire != NULL) { liberation_generateur_aleatoire(s_etat_processus); } if ((*s_etat_processus).instruction_derniere_erreur != NULL) { free((*s_etat_processus).instruction_derniere_erreur); (*s_etat_processus).instruction_derniere_erreur = NULL; } element_courant = (void *) (*s_etat_processus) .l_base_pile_processus; while(element_courant != NULL) { pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); element_suivant = (*((struct_liste_chainee *) element_courant)) .suivant; free((struct_liste_chainee *) element_courant); element_courant = element_suivant; } pthread_mutex_trylock(&((*(*s_etat_processus).indep).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus).indep).mutex)); liberation(s_etat_processus, (*s_etat_processus).indep); pthread_mutex_trylock(&((*(*s_etat_processus).depend).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus).depend).mutex)); liberation(s_etat_processus, (*s_etat_processus).depend); free((*s_etat_processus).label_x); free((*s_etat_processus).label_y); free((*s_etat_processus).label_z); free((*s_etat_processus).titre); free((*s_etat_processus).legende); pthread_mutex_trylock(&((*(*s_etat_processus) .parametres_courbes_de_niveau).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus) .parametres_courbes_de_niveau).mutex)); liberation(s_etat_processus, (*s_etat_processus) .parametres_courbes_de_niveau); for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++) { if ((*s_etat_processus).corps_interruptions[i] != NULL) { pthread_mutex_trylock(&((*(*s_etat_processus) .corps_interruptions[i]).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus) .corps_interruptions[i]).mutex)); liberation(s_etat_processus, (*s_etat_processus).corps_interruptions[i]); } element_courant = (*s_etat_processus) .pile_origine_interruptions[i]; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)) .donnee); free(element_courant); element_courant = element_suivant; } } for(i = 0; i < (*s_etat_processus).nombre_variables; i++) { pthread_mutex_trylock(&((*(*s_etat_processus) .s_liste_variables[i].objet).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus) .s_liste_variables[i].objet).mutex)); // Les variables de niveau 0 sont des définitions qui // ne sont pas copiées entre threads. if ((*s_etat_processus).s_liste_variables[i].niveau > 0) { liberation(s_etat_processus, (*s_etat_processus).s_liste_variables[i].objet); } free((*s_etat_processus).s_liste_variables[i].nom); } free((*s_etat_processus).s_liste_variables); for(i = 0; i < (*s_etat_processus).nombre_variables_statiques; i++) { pthread_mutex_trylock(&((*(*s_etat_processus) .s_liste_variables_statiques[i].objet).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus) .s_liste_variables_statiques[i].objet).mutex)); liberation(s_etat_processus, (*s_etat_processus) .s_liste_variables_statiques[i].objet); free((*s_etat_processus).s_liste_variables_statiques[i].nom); } free((*s_etat_processus).s_liste_variables_statiques); // Ne peut être effacé qu'une seule fois if (suppression_variables_partagees == d_faux) { suppression_variables_partagees = d_vrai; for(i = 0; i < (*(*s_etat_processus) .s_liste_variables_partagees).nombre_variables; i++) { pthread_mutex_trylock(&((*(*(*s_etat_processus) .s_liste_variables_partagees).table[i].objet) .mutex)); pthread_mutex_unlock(&((*(*(*s_etat_processus) .s_liste_variables_partagees).table[i].objet) .mutex)); liberation(s_etat_processus, (*(*s_etat_processus) .s_liste_variables_partagees).table[i].objet); free((*(*s_etat_processus).s_liste_variables_partagees) .table[i].nom); } if ((*(*s_etat_processus).s_liste_variables_partagees).table != NULL) { free((struct_variable_partagee *) (*(*s_etat_processus) .s_liste_variables_partagees).table); } pthread_mutex_trylock(&((*(*s_etat_processus) .s_liste_variables_partagees).mutex)); pthread_mutex_unlock(&((*(*s_etat_processus) .s_liste_variables_partagees).mutex)); } element_courant = (*s_etat_processus).l_base_pile; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free((struct_liste_chainee *) element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).l_base_pile_contextes; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free((struct_liste_chainee *) element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).l_base_pile_taille_contextes; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free((struct_liste_chainee *) element_courant); element_courant = element_suivant; } for(i = 0; i < (*s_etat_processus).nombre_instructions_externes; i++) { free((*s_etat_processus).s_instructions_externes[i].nom); free((*s_etat_processus).s_instructions_externes[i] .nom_bibliotheque); } if ((*s_etat_processus).nombre_instructions_externes != 0) { free((*s_etat_processus).s_instructions_externes); } element_courant = (*s_etat_processus).s_bibliotheques; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; element_candidat = (*candidat).s_bibliotheques; while(element_candidat != NULL) { if (((*((struct_bibliotheque *) (*((struct_liste_chainee *) element_courant)).donnee)) .descripteur == (*((struct_bibliotheque *) (*((struct_liste_chainee *) element_candidat)) .donnee)).descripteur) && ((*((struct_bibliotheque *) (*((struct_liste_chainee *) element_courant)) .donnee)).pid == (*((struct_bibliotheque *) (*((struct_liste_chainee *) element_candidat)) .donnee)).pid) && (pthread_equal( (*((struct_bibliotheque *) (*((struct_liste_chainee *) element_courant)) .donnee)).tid, (*((struct_bibliotheque *) (*((struct_liste_chainee *) element_candidat)) .donnee)).tid) != 0)) { break; } element_candidat = (*((struct_liste_chainee *) element_candidat)).suivant; } if (element_candidat == NULL) { dlclose((*((struct_bibliotheque *) (*((struct_liste_chainee *) element_courant)) .donnee)).descripteur); } free((*((struct_bibliotheque *) (*((struct_liste_chainee *) element_courant)).donnee)).nom); free((*((struct_liste_chainee *) element_courant)).donnee); free(element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).l_base_pile_last; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free(element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).l_base_pile_systeme; while(element_courant != NULL) { element_suivant = (*((struct_liste_pile_systeme *) element_courant)).suivant; if ((*((struct_liste_pile_systeme *) element_courant)).indice_boucle != NULL) { pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *) element_courant)).indice_boucle).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *) element_courant)).indice_boucle).mutex)); } liberation(s_etat_processus, (*((struct_liste_pile_systeme *) element_courant)).indice_boucle); if ((*((struct_liste_pile_systeme *) element_courant)).limite_indice_boucle != NULL) { pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *) element_courant)).limite_indice_boucle).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *) element_courant)).limite_indice_boucle).mutex)); } liberation(s_etat_processus, (*((struct_liste_pile_systeme *) element_courant)).limite_indice_boucle); if ((*((struct_liste_pile_systeme *) element_courant)).objet_de_test != NULL) { pthread_mutex_trylock(&((*(*((struct_liste_pile_systeme *) element_courant)).objet_de_test).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_pile_systeme *) element_courant)).objet_de_test).mutex)); } liberation(s_etat_processus, (*((struct_liste_pile_systeme *) element_courant)).objet_de_test); if ((*((struct_liste_pile_systeme *) element_courant)).nom_variable != NULL) { free((*((struct_liste_pile_systeme *) element_courant)).nom_variable); } free(element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).s_fichiers; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; element_candidat = (*candidat).s_fichiers; while(element_candidat != NULL) { if (((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).pid == (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)) .donnee)).pid) && (pthread_equal( (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).tid, (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)) .donnee)).tid) != 0)) { if ((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).type == (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)) .donnee)).type) { if ((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)).donnee)).type == 'C') { if ((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)).donnee)) .descripteur_c == (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)).donnee)) .descripteur_c) { break; } } else { if (((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)).donnee)) .descripteur_sqlite == (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)).donnee)) .descripteur_sqlite) && ((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)).donnee)) .descripteur_c == (*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_candidat)).donnee)) .descripteur_c)) { break; } } } } element_candidat = (*((struct_liste_chainee *) element_candidat)).suivant; } if (element_candidat == NULL) { fclose((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).descripteur_c); if ((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).type != 'C') { sqlite3_close((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)) .donnee)).descripteur_sqlite); } } free((*((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)).donnee)).nom); free((struct_descripteur_fichier *) (*((struct_liste_chainee *) element_courant)).donnee); free(element_courant); element_courant = element_suivant; } element_courant = (*s_etat_processus).s_sockets; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; element_candidat = (*candidat).s_sockets; while(element_candidat != NULL) { if (((*((struct_socket *) (*((struct_liste_chainee *) element_courant)) .donnee)).socket == (*((struct_socket *) (*((struct_liste_chainee *) element_candidat)) .donnee)).socket) && ((*((struct_socket *) (*((struct_liste_chainee *) element_courant)) .donnee)).pid == (*((struct_socket *) (*((struct_liste_chainee *) element_candidat)) .donnee)).pid) && (pthread_equal( (*((struct_socket *) (*((struct_liste_chainee *) element_courant)) .donnee)).tid, (*((struct_socket *) (*((struct_liste_chainee *) element_candidat)) .donnee)).tid) != 0)) { break; } element_candidat = (*((struct_liste_chainee *) element_candidat)).suivant; } if (element_candidat == NULL) { if ((*((struct_socket *) (*((struct_liste_chainee *) element_courant)).donnee)).socket_connectee == d_vrai) { shutdown((*((struct_socket *) (*((struct_liste_chainee *) element_courant)) .donnee)).socket, SHUT_RDWR); } close((*((struct_socket *) (*((struct_liste_chainee *) element_courant)) .donnee)).socket); } pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free(element_courant); element_courant = element_suivant; } /* ================================================================================ À noter : on ne ferme pas la connexion car la conséquence immédiate est une destruction de l'objet pour le processus père. ================================================================================ element_courant = (*s_etat_processus).s_connecteurs_sql; while(element_courant != NULL) { element_suivant = (*((struct_liste_chainee *) element_courant)).suivant; element_candidat = (*candidat).s_connecteurs_sql; while(element_candidat != NULL) { if ((( #ifdef MYSQL_SUPPORT ((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).descripteur.mysql == (*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).descripteur.mysql) && (strcmp((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).type, "MYSQL") == 0) && (strcmp((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).type, "MYSQL") == 0) #else 0 #endif ) || ( #ifdef POSTGRESQL_SUPPORT ((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).descripteur.postgresql == (*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).descripteur.postgresql) && (strcmp((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).type, "POSTGRESQL") == 0) && (strcmp((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).type, "POSTGRESQL") == 0) #else 0 #endif )) && ((*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).pid == (*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).pid) && (pthread_equal( (*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_courant)) .donnee)).tid, (*((struct_connecteur_sql *) (*((struct_liste_chainee *) element_candidat)) .donnee)).tid) != 0)) { break; } element_candidat = (*((struct_liste_chainee *) element_candidat)).suivant; } if (element_candidat == NULL) { sqlclose((*((struct_liste_chainee *) element_courant)) .donnee); } pthread_mutex_trylock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); pthread_mutex_unlock(&((*(*((struct_liste_chainee *) element_courant)).donnee).mutex)); liberation(s_etat_processus, (*((struct_liste_chainee *) element_courant)).donnee); free(element_courant); element_courant = element_suivant; } */ (*s_etat_processus).s_connecteurs_sql = NULL; element_courant = (*s_etat_processus).s_marques; while(element_courant != NULL) { free((*((struct_marque *) element_courant)).label); free((*((struct_marque *) element_courant)).position); element_suivant = (*((struct_marque *) element_courant)) .suivant; free(element_courant); element_courant = element_suivant; } liberation_allocateur(s_etat_processus); # ifndef SEMAPHORES_NOMMES sem_post(&((*s_etat_processus).semaphore_fork)); sem_destroy(&((*s_etat_processus).semaphore_fork)); # else sem_post((*s_etat_processus).semaphore_fork); sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork); # endif free(s_etat_processus); s_etat_processus = candidat; } l_element_suivant = (*l_element_courant).suivant; free((struct_thread *) (*l_element_courant).donnee); free((struct_liste_chainee *) l_element_courant); l_element_courant = l_element_suivant; } liste_threads = NULL; l_element_courant = liste_threads_surveillance; while(l_element_courant != NULL) { s_argument_thread = (struct_descripteur_thread *) (*l_element_courant).donnee; close((*s_argument_thread).pipe_objets[0]); close((*s_argument_thread).pipe_acquittement[1]); close((*s_argument_thread).pipe_injections[1]); close((*s_argument_thread).pipe_nombre_injections[1]); close((*s_argument_thread).pipe_nombre_objets_attente[0]); close((*s_argument_thread).pipe_interruptions[0]); close((*s_argument_thread).pipe_nombre_interruptions_attente[0]); if (pthread_mutex_lock(&((*s_argument_thread).mutex)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; sem_post(&semaphore_liste_threads); return; } (*s_argument_thread).nombre_references--; BUG((*s_argument_thread).nombre_references < 0, printf("(*s_argument_thread).nombre_references = %d\n", (int) (*s_argument_thread).nombre_references)); if ((*s_argument_thread).nombre_references == 0) { if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; sem_post(&semaphore_liste_threads); return; } pthread_mutex_destroy(&((*s_argument_thread).mutex)); free(s_argument_thread); } else { if (pthread_mutex_unlock(&((*s_argument_thread).mutex)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; sem_post(&semaphore_liste_threads); return; } } l_element_suivant = (*l_element_courant).suivant; free((struct_liste_chainee *) l_element_courant); l_element_courant = l_element_suivant; } liste_threads_surveillance = NULL; # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); (*s_etat_processus).erreur_systeme = d_es_processus; return; } pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } static struct_processus * recherche_thread(pid_t pid, pthread_t tid) { volatile struct_liste_chainee_volatile *l_element_courant; struct_processus *s_etat_processus; l_element_courant = liste_threads; while(l_element_courant != NULL) { if ((pthread_equal((*((struct_thread *) (*l_element_courant).donnee)) .tid, tid) != 0) && ((*((struct_thread *) (*l_element_courant).donnee)).pid == pid)) { break; } l_element_courant = (*l_element_courant).suivant; } if (l_element_courant == NULL) { /* * Le processus n'existe plus. On ne distribue aucun signal. */ return(NULL); } s_etat_processus = (*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus; return(s_etat_processus); } static logical1 recherche_thread_principal(pid_t pid, pthread_t *thread) { volatile struct_liste_chainee_volatile *l_element_courant; l_element_courant = liste_threads; while(l_element_courant != NULL) { if (((*((struct_thread *) (*l_element_courant).donnee)).thread_principal == d_vrai) && ((*((struct_thread *) (*l_element_courant).donnee)).pid == pid)) { break; } l_element_courant = (*l_element_courant).suivant; } if (l_element_courant == NULL) { /* * Le processus n'existe plus. On ne distribue aucun signal. */ return(d_faux); } (*thread) = (*((struct_thread *) (*l_element_courant).donnee)).tid; return(d_vrai); } /* ================================================================================ Procédures de gestion des signaux d'interruption ================================================================================ Entrée : variable globale -------------------------------------------------------------------------------- Sortie : variable globale modifiée -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ // Les routines suivantes sont uniquement appelées depuis les gestionnaires // des signaux asynchrones. Elles de doivent pas bloquer dans le cas où // les sémaphores sont déjà bloqués par un gestionnaire de signal. static inline void verrouillage_gestionnaire_signaux() { int semaphore; sigset_t oldset; sigset_t set; sem_t *sem; if ((sem = pthread_getspecific(semaphore_fork_processus_courant)) != NULL) { if (sem_post(sem) != 0) { BUG(1, uprintf("Lock error !\n")); return; } } // Il faut respecteur l'atomicité des deux opérations suivantes ! sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1) # else while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_gestionnaires_signaux) == -1) # else if (sem_post(semaphore_gestionnaires_signaux) == -1) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Lock error !\n")); return; } # ifndef SEMAPHORES_NOMMES if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0) # else if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Lock error !\n")); return; } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0) # else if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } if (semaphore == 1) { // Le semaphore ne peut être pris par le thread qui a appelé // le gestionnaire de signal car le signal est bloqué par ce thread // dans les zones critiques. Ce sémaphore ne peut donc être bloqué que // par un thread concurrent. On essaye donc de le bloquer jusqu'à // ce que ce soit possible. # ifndef SEMAPHORES_NOMMES while(sem_trywait(&semaphore_liste_threads) == -1) # else while(sem_trywait(semaphore_liste_threads) == -1) # endif { if ((errno != EINTR) && (errno != EAGAIN)) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); while(sem_wait(sem) == -1) { if (errno != EINTR) { BUG(1, uprintf("Lock error !\n")); return; } } BUG(1, uprintf("Lock error !\n")); return; } sched_yield(); } } pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } static inline void deverrouillage_gestionnaire_signaux() { int semaphore; sem_t *sem; sigset_t oldset; sigset_t set; // Il faut respecteur l'atomicité des deux opérations suivantes ! sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_gestionnaires_signaux_atomique) == -1) # else while(sem_wait(semaphore_gestionnaires_signaux_atomique) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } } # ifndef SEMAPHORES_NOMMES if (sem_getvalue(&semaphore_gestionnaires_signaux, &semaphore) != 0) # else if (sem_getvalue(semaphore_gestionnaires_signaux, &semaphore) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } # ifndef SEMAPHORES_NOMMES while(sem_wait(&semaphore_gestionnaires_signaux) == -1) # else while(sem_wait(semaphore_gestionnaires_signaux) == -1) # endif { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } } # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_gestionnaires_signaux_atomique) != 0) # else if (sem_post(semaphore_gestionnaires_signaux_atomique) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } if ((sem = pthread_getspecific(semaphore_fork_processus_courant)) != NULL) { while(sem_wait(sem) == -1) { if (errno != EINTR) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } } } if (semaphore == 1) { # ifndef SEMAPHORES_NOMMES if (sem_post(&semaphore_liste_threads) != 0) # else if (sem_post(semaphore_liste_threads) != 0) # endif { pthread_sigmask(SIG_SETMASK, &oldset, NULL); BUG(1, uprintf("Unlock error !\n")); return; } } pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); return; } void interruption1(int signal, siginfo_t *siginfo, void *context) { pthread_t thread; struct_processus *s_etat_processus; volatile sig_atomic_t exclusion = 0; verrouillage_gestionnaire_signaux(); switch(signal) { case SIGALRM : { if ((*siginfo).si_pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGALRM (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } if ((*s_etat_processus).pid_processus_pere != getpid()) { kill((*s_etat_processus).pid_processus_pere, signal); } else { (*s_etat_processus).var_volatile_alarme = -1; (*s_etat_processus).var_volatile_requete_arret = -1; } } else { if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, signal); } } break; } case SIGINT : { /* * Une vieille spécification POSIX permet au pointeur siginfo * d'être nul dans le cas d'un ^C envoyé depuis le clavier. * Solaris suit en particulier cette spécification. */ if (siginfo == NULL) { kill(getpid(), signal); } else if ((*siginfo).si_pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGINT (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } if ((*s_etat_processus).pid_processus_pere != getpid()) { kill((*s_etat_processus).pid_processus_pere, signal); } else { (*s_etat_processus).var_volatile_traitement_sigint = -1; while(exclusion == 1); exclusion = 1; if ((*s_etat_processus).var_volatile_requete_arret == -1) { deverrouillage_gestionnaire_signaux(); exclusion = 0; return; } if (strncmp(getenv("LANG"), "fr", 2) == 0) { printf("+++Interruption\n"); } else { printf("+++Interrupt\n"); } fflush(stdout); (*s_etat_processus).var_volatile_requete_arret = -1; (*s_etat_processus).var_volatile_alarme = -1; exclusion = 0; } } else { if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, signal); } } break; } default : { BUG(1, uprintf("[%d] Unknown signal %d in this context\n", (int) getpid(), signal)); break; } } deverrouillage_gestionnaire_signaux(); return; } void interruption2(int signal, siginfo_t *siginfo, void *context) { pthread_t thread; struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if (siginfo == NULL) { /* * Le signal SIGFSTP provient de la mort du processus de contrôle. * Sous certains systèmes (Linux...), la mort du terminal de contrôle * se traduit par l'envoi d'un SIGHUP au processus. Sur d'autres * (SunOS), le processus reçoit un SIGFSTP avec une structure siginfo * non initialisée (pointeur NULL) issue de TERMIO. */ if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, SIGHUP); deverrouillage_gestionnaire_signaux(); return; } } else if ((*siginfo).si_pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } /* * 0 => fonctionnement normal * -1 => requête * 1 => requête acceptée en attente de traitement */ if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGTSTP (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } if ((*s_etat_processus).var_volatile_processus_pere == 0) { kill((*s_etat_processus).pid_processus_pere, signal); } else { (*s_etat_processus).var_volatile_requete_arret2 = -1; } } else { // Envoi d'un signal au thread maître du groupe. if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, SIGTSTP); deverrouillage_gestionnaire_signaux(); return; } } deverrouillage_gestionnaire_signaux(); return; } void interruption3(int signal, siginfo_t *siginfo, void *context) { struct_processus *s_etat_processus; static int compteur = 0; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGSEGV (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } if ((*s_etat_processus).var_volatile_recursivite == -1) { // Segfault dans un appel de fonction récursive deverrouillage_gestionnaire_signaux(); longjmp(contexte, -1); } else { // Segfault dans une routine interne if (strncmp(getenv("LANG"), "fr", 2) == 0) { printf("+++Système : Violation d'accès (dépassement de pile)\n"); } else { printf("+++System : Access violation (stack overflow)\n"); } fflush(stdout); compteur++; if (compteur > 1) { deverrouillage_gestionnaire_signaux(); exit(EXIT_FAILURE); } else { deverrouillage_gestionnaire_signaux(); longjmp(contexte_initial, -1); } } deverrouillage_gestionnaire_signaux(); return; } void interruption4(int signal, siginfo_t *siginfo, void *context) { struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } /* * Démarrage d'un processus fils ou gestion de SIGCONT (SUSPEND) */ if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGSTART/SIGCONT (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } deverrouillage_gestionnaire_signaux(); return; } void interruption5(int signal, siginfo_t *siginfo, void *context) { pthread_t thread; struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((*siginfo).si_pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (signal == SIGFABORT) { (*s_etat_processus).arret_depuis_abort = -1; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { if (signal == SIGFSTOP) { printf("[%d] SIGFSTOP (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } else { printf("[%d] SIGFABORT (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } } /* * var_globale_traitement_retarde_stop : * 0 -> traitement immédiat * 1 -> traitement retardé (aucun signal reçu) * -1 -> traitement retardé (un ou plusieurs signaux stop reçus) */ if ((*s_etat_processus).var_volatile_traitement_retarde_stop == 0) { (*s_etat_processus).var_volatile_requete_arret = -1; } else { (*s_etat_processus).var_volatile_traitement_retarde_stop = -1; } } else { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (signal == SIGFABORT) { (*s_etat_processus).arret_depuis_abort = -1; } // Envoi d'un signal au thread maître du groupe. if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, signal); deverrouillage_gestionnaire_signaux(); return; } } deverrouillage_gestionnaire_signaux(); return; } void interruption6(int signal, siginfo_t *siginfo, void *context) { struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGINJECT/SIGQUIT (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } deverrouillage_gestionnaire_signaux(); return; } void interruption7(int signal, siginfo_t *siginfo, void *context) { struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGPIPE (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } (*s_etat_processus).var_volatile_requete_arret = -1; deverrouillage_gestionnaire_signaux(); BUG(1, printf("[%d] SIGPIPE\n", (int) getpid())); return; } void interruption8(int signal, siginfo_t *siginfo, void *context) { pthread_t thread; struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((*siginfo).si_pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGURG (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } (*s_etat_processus).var_volatile_alarme = -1; (*s_etat_processus).var_volatile_requete_arret = -1; } else { // Envoi d'un signal au thread maître du groupe. if (recherche_thread_principal(getpid(), &thread) == d_vrai) { pthread_kill(thread, SIGURG); deverrouillage_gestionnaire_signaux(); return; } } deverrouillage_gestionnaire_signaux(); return; } void interruption9(int signal, siginfo_t *siginfo, void *context) { struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGABORT/SIGPROF (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } pthread_kill((*s_etat_processus).tid_processus_pere, SIGFABORT); deverrouillage_gestionnaire_signaux(); return; } void interruption10(int signal, siginfo_t *siginfo, void *context) { file *fichier; struct_processus *s_etat_processus; unsigned char nom[8 + 64 + 1]; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } snprintf(nom, 8 + 64 + 1, "rpl-out-%lu-%lu", (unsigned long) getpid(), (unsigned long) pthread_self()); if ((fichier = fopen(nom, "w+")) != NULL) { fclose(fichier); freopen(nom, "w", stdout); freopen(nom, "w", stderr); } freopen("/dev/null", "r", stdin); if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) { printf("[%d] SIGHUP (thread %llu)\n", (int) getpid(), (unsigned long long) pthread_self()); fflush(stdout); } deverrouillage_gestionnaire_signaux(); return; } void traitement_exceptions_gsl(const char *reason, const char *file, int line, int gsl_errno) { struct_processus *s_etat_processus; verrouillage_gestionnaire_signaux(); if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); return; } (*s_etat_processus).var_volatile_exception_gsl = gsl_errno; deverrouillage_gestionnaire_signaux(); return; } // vim: ts=4