--- rpl/src/interruptions.c 2012/01/05 10:19:05 1.90 +++ rpl/src/interruptions.c 2012/10/01 11:05:08 1.102 @@ -1,6 +1,6 @@ /* ================================================================================ - RPL/2 (R) version 4.1.5 + RPL/2 (R) version 4.1.11 Copyright (C) 1989-2012 Dr. BERTRAND Joël This file is part of RPL/2. @@ -52,7 +52,6 @@ typedef struct liste_chainee_volatile 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 @@ -64,6 +63,117 @@ unsigned char *racine_segment; static pthread_mutex_t mutex_interruptions = PTHREAD_MUTEX_INITIALIZER; +static void * +thread_surveillance_signaux(void *argument) +{ + // Cette fonction est lancée dans un thread créé par processus pour + // gérer le cas des appels système qui seraient bloqués lors de l'arrivée du + // signal SIGALRM. Les processus externes n'envoient plus un signal au + // processus ou au thread à signaler mais positionnent les informations + // nécessaires dans la queue des signaux et incrémentent le sémaphore. + // Le sémaphore est décrémenté lorsque le signal est effectivement traité. + + int nombre_signaux_envoyes; + + struct_processus *s_etat_processus; + + struct timespec attente; + + volatile struct_liste_chainee_volatile *l_element_courant; + + s_etat_processus = (struct_processus *) argument; + + for(;;) + { + attente.tv_sec = 0; + attente.tv_nsec = GRANULARITE_us * 1000; + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + if (sem_wait(&(*s_queue_signaux).signalisation) == 0) +# else + if(sem_wait(semaphore_signalisation) == 0) +# endif + { + if ((*s_queue_signaux).requete_arret == d_vrai) + { + break; + } + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_post(&(*s_queue_signaux).signalisation); +# else + sem_post(semaphore_signalisation); +# endif + + nombre_signaux_envoyes = 0; + sched_yield(); + + // Dans un premier temps, on verrouille la queue des signaux + // affectée au processus courant pour vérifier s'il y a quelque + // chose à traiter. + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_wait(&(*s_queue_signaux).semaphore); +# else + sem_wait(semaphore_queue_signaux); +# endif + + if ((*s_queue_signaux).pointeur_lecture != + (*s_queue_signaux).pointeur_ecriture) + { + nombre_signaux_envoyes++; + raise(SIGALRM); + } + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_post(&(*s_queue_signaux).semaphore); +# else + sem_post(semaphore_queue_signaux); +# endif + + // Dans un second temps, on balaye toutes les queues de signaux + // des threads du processus courant. + + pthread_mutex_lock(&mutex_liste_threads); + l_element_courant = liste_threads; + + while(l_element_courant != NULL) + { + if ((*((struct_thread *) (*l_element_courant).donnee)).pid + == getpid()) + { + if ((*(*((struct_thread *) (*l_element_courant).donnee)) + .s_etat_processus).pointeur_signal_ecriture != + (*(*((struct_thread *) (*l_element_courant).donnee)) + .s_etat_processus).pointeur_signal_lecture) + { + nombre_signaux_envoyes++; + pthread_kill((*((struct_thread *) (*l_element_courant) + .donnee)).tid, SIGALRM); + } + } + + l_element_courant = (*l_element_courant).suivant; + } + + pthread_mutex_unlock(&mutex_liste_threads); + + // Nanosleep + + if (nombre_signaux_envoyes > 0) + { + nanosleep(&attente, NULL); + } + } + else + { + (*s_etat_processus).erreur_systeme = d_es_processus; + } + } + + pthread_exit(NULL); +} + void modification_pid_thread_pere(struct_processus *s_etat_processus) { @@ -207,6 +317,26 @@ retrait_thread(struct_processus *s_etat_ return; } + // Le thread ne peut plus traiter de signaux explicites. Il convient + // alors de corriger le sémaphore pour annuler les signaux en attente. + + while((*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus) + .pointeur_signal_ecriture != (*(*((struct_thread *) + (*l_element_courant).donnee)).s_etat_processus) + .pointeur_signal_lecture) + { +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_wait(&((*s_queue_signaux).signalisation)); +# else + sem_wait(semaphore_signalisation); +# endif + + (*(*((struct_thread *) (*l_element_courant).donnee)).s_etat_processus) + .pointeur_signal_lecture = ((*(*((struct_thread *) + (*l_element_courant).donnee)).s_etat_processus) + .pointeur_signal_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX; + } + free((void *) (*l_element_courant).donnee); free((struct_liste_chainee_volatile *) l_element_courant); @@ -1492,7 +1622,7 @@ deverrouillage_gestionnaire_signaux(stru if (signal_test == SIGTEST) { signal_test = signal; return; } // Récupération des signaux -// - SIGINT (arrêt au clavier) +// - SIGINT (arrêt au clavier) // - SIGTERM (signal d'arrêt en provenance du système) void @@ -1571,7 +1701,7 @@ inline static void signal_term(struct_processus *s_etat_processus, pid_t pid) { struct_processus *s_thread_principal; - volatile sig_atomic_t exclusion = 0; + pthread_mutex_t exclusion = PTHREAD_MUTEX_INITIALIZER; verrouillage_gestionnaire_signaux(s_etat_processus); @@ -1593,20 +1723,19 @@ signal_term(struct_processus *s_etat_pro { (*s_etat_processus).var_volatile_traitement_sigint = -1; - while(exclusion == 1); - exclusion = 1; + pthread_mutex_lock(&exclusion); if ((*s_etat_processus).var_volatile_requete_arret == -1) { deverrouillage_gestionnaire_signaux(s_etat_processus); - exclusion = 0; + pthread_mutex_unlock(&exclusion); return; } (*s_etat_processus).var_volatile_requete_arret = -1; (*s_etat_processus).var_volatile_alarme = -1; - exclusion = 0; + pthread_mutex_unlock(&exclusion); } } else @@ -2268,13 +2397,13 @@ scrutation_interruptions(struct_processu // à lire. Les pointeurs d'écriture pointent sur les prochains éléments à // écrire. -# ifndef SEMAPHORES_NOMMES +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) if (sem_trywait(&((*s_queue_signaux).semaphore)) == 0) # else if (sem_trywait(semaphore_queue_signaux) == 0) # endif { - if ((*s_queue_signaux).pointeur_lecture != + while((*s_queue_signaux).pointeur_lecture != (*s_queue_signaux).pointeur_ecriture) { // Il y a un signal en attente dans le segment partagé. On le @@ -2287,9 +2416,15 @@ scrutation_interruptions(struct_processu (*s_queue_signaux).pointeur_lecture = ((*s_queue_signaux).pointeur_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX; + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_wait(&((*s_queue_signaux).signalisation)); +# else + sem_wait(semaphore_signalisation); +# endif } -# ifndef SEMAPHORES_NOMMES +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) sem_post(&((*s_queue_signaux).semaphore)); # else sem_post(semaphore_queue_signaux); @@ -2300,7 +2435,7 @@ scrutation_interruptions(struct_processu if (pthread_mutex_trylock(&mutex_interruptions) == 0) { - if ((*s_etat_processus).pointeur_signal_lecture != + while((*s_etat_processus).pointeur_signal_lecture != (*s_etat_processus).pointeur_signal_ecriture) { // Il y a un signal dans la queue du thread courant. On le traite. @@ -2312,6 +2447,12 @@ scrutation_interruptions(struct_processu (*s_etat_processus).pointeur_signal_lecture = ((*s_etat_processus).pointeur_signal_lecture + 1) % LONGUEUR_QUEUE_SIGNAUX; + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_wait(&((*s_queue_signaux).signalisation)); +# else + sem_wait(semaphore_signalisation); +# endif } pthread_mutex_unlock(&mutex_interruptions); @@ -2394,6 +2535,7 @@ envoi_signal_processus(pid_t pid, enum s # ifndef IPCS_SYSV # ifdef SEMAPHORES_NOMMES sem_t *semaphore; + sem_t *signalisation; # endif # else # ifndef OS2 @@ -2418,7 +2560,7 @@ envoi_signal_processus(pid_t pid, enum s return(1); } -# ifndef SEMAPHORES_NOMMES +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) while(sem_wait(&((*s_queue_signaux).semaphore)) != 0) # else while(sem_wait(semaphore_queue_signaux) != 0) @@ -2439,7 +2581,7 @@ envoi_signal_processus(pid_t pid, enum s ((*s_queue_signaux).pointeur_ecriture + 1) % LONGUEUR_QUEUE_SIGNAUX; -# ifndef SEMAPHORES_NOMMES +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) if (sem_post(&((*s_queue_signaux).semaphore)) != 0) # else if (sem_post(semaphore_queue_signaux) != 0) @@ -2447,6 +2589,15 @@ envoi_signal_processus(pid_t pid, enum s { return(1); } + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + if (sem_post(&((*s_queue_signaux).signalisation)) != 0) +# else + if (sem_post(semaphore_signalisation) != 0) +# endif + { + return(1); + } } else { @@ -2533,11 +2684,18 @@ envoi_signal_processus(pid_t pid, enum s return(1); } + if ((signalisation = sem_open2(pid, SEM_SIGNALISATION)) + == SEM_FAILED) + { + return(1); + } + while(sem_wait(semaphore) != 0) { if (errno != EINTR) { sem_close(semaphore); + sem_close(signalisation); return(1); } } @@ -2564,10 +2722,16 @@ envoi_signal_processus(pid_t pid, enum s { return(1); } + + if (sem_post(&((*queue).signalisation)) != 0) + { + return(1); + } # else if (sem_post(semaphore) != 0) { sem_close(semaphore); + sem_close(signalisation); return(1); } @@ -2575,6 +2739,18 @@ envoi_signal_processus(pid_t pid, enum s { return(1); } + + if (sem_post(signalisation) != 0) + { + sem_close(signalisation); + return(1); + } + + if (sem_close(signalisation) != 0) + { + return(1); + } + # endif if (munmap(queue, sizeof(struct_queue_signaux)) != 0) @@ -2588,6 +2764,11 @@ envoi_signal_processus(pid_t pid, enum s return(1); } + if (sem_post(&((*queue).signalisation)) != 0) + { + return(1); + } + # ifndef OS2 // SysV if (shmdt(queue) != 0) { @@ -2599,8 +2780,6 @@ envoi_signal_processus(pid_t pid, enum s # endif } - kill(pid, SIGALRM); - return(0); } @@ -2664,7 +2843,17 @@ envoi_signal_thread(pthread_t tid, enum return(1); } - pthread_kill(tid, SIGALRM); +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + if (sem_post(&((*s_queue_signaux).signalisation)) != 0) + { + return(1); + } +# else + if (sem_post(semaphore_signalisation) != 0) + { + return(1); + } +# endif return(0); } @@ -2682,7 +2871,17 @@ envoi_signal_contexte(struct_processus * % LONGUEUR_QUEUE_SIGNAUX; pthread_mutex_unlock(&mutex_interruptions); - pthread_kill((*s_etat_processus_a_signaler).tid, SIGALRM); +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + if (sem_post(&((*s_queue_signaux).signalisation)) != 0) + { + return(1); + } +# else + if (sem_post(semaphore_signalisation) != 0) + { + return(1); + } +# endif return(0); } @@ -2704,6 +2903,8 @@ envoi_signal_contexte(struct_processus * void creation_queue_signaux(struct_processus *s_etat_processus) { + pthread_attr_t attributs; + unsigned char *nom; racine_segment = (*s_etat_processus).chemin_fichiers_temporaires; @@ -2752,6 +2953,7 @@ creation_queue_signaux(struct_processus # ifndef SEMAPHORES_NOMMES sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); # else if ((semaphore_queue_signaux = sem_init2(1, getpid(), SEM_QUEUE)) == SEM_FAILED) @@ -2759,10 +2961,18 @@ creation_queue_signaux(struct_processus (*s_etat_processus).erreur_systeme = d_es_processus; return; } + + if ((semaphore_signalisation = sem_init2(1, getpid(), + SEM_SIGNALISATION)) == SEM_FAILED) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } # endif (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; if (msync(s_queue_signaux, sizeof(struct_queue_signaux), 0)) { @@ -2826,8 +3036,10 @@ creation_queue_signaux(struct_processus } sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; # else // OS/2 if ((nom = nom_segment(NULL, getpid())) == NULL) { @@ -2847,11 +3059,65 @@ creation_queue_signaux(struct_processus free(nom); sem_init(&((*s_queue_signaux).semaphore), 1, 1); + sem_init(&((*s_queue_signaux).signalisation), 1, 0); (*s_queue_signaux).pointeur_lecture = 0; (*s_queue_signaux).pointeur_ecriture = 0; + (*s_queue_signaux).requete_arret = d_faux; # endif # endif + // Lancement du thread de récupération des signaux. + + if (pthread_attr_init(&attributs) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_attr_setdetachstate(&attributs, + PTHREAD_CREATE_JOINABLE) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + +# ifdef SCHED_OTHER + if (pthread_attr_setschedpolicy(&attributs, SCHED_OTHER) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + +# ifdef PTHREAD_EXPLICIT_SCHED + if (pthread_attr_setinheritsched(&attributs, PTHREAD_EXPLICIT_SCHED) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + +# ifdef PTHREAD_SCOPE_SYSTEM + if (pthread_attr_setscope(&attributs, PTHREAD_SCOPE_SYSTEM) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } +# endif + + if (pthread_attr_destroy(&attributs) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + if (pthread_create(&((*s_queue_signaux).thread_signaux), &attributs, + thread_surveillance_signaux, s_etat_processus) != 0) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + return; } @@ -2872,6 +3138,18 @@ creation_queue_signaux(struct_processus void liberation_queue_signaux(struct_processus *s_etat_processus) { + // Incrémenter le sémaphore pour être sûr de le débloquer. + + (*s_queue_signaux).requete_arret = d_vrai; + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_post(&((*s_queue_signaux).signalisation)); +# else + sem_post(semaphore_signalisation); +# endif + + pthread_join((*s_queue_signaux).thread_signaux, NULL); + # ifdef IPCS_SYSV // SystemV # ifndef OS2 if (shmdt(s_queue_signaux) == -1) @@ -2884,8 +3162,10 @@ liberation_queue_signaux(struct_processu # else // POSIX # ifndef SEMAPHORES_NOMMES sem_close(&((*s_queue_signaux).semaphore)); + sem_close(&((*s_queue_signaux).signalisation)); # else sem_close(semaphore_queue_signaux); + sem_close(semaphore_signalisation); # endif if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0) @@ -2921,6 +3201,18 @@ destruction_queue_signaux(struct_process unsigned char *nom; # endif + // Incrémenter le sémaphore pour être sûr de le débloquer. + + (*s_queue_signaux).requete_arret = d_vrai; + +# if (!defined(SEMAPHORES_NOMMES)) || defined(IPCS_SYSV) + sem_post(&((*s_queue_signaux).signalisation)); +# else + sem_post(semaphore_signalisation); +# endif + + pthread_join((*s_queue_signaux).thread_signaux, NULL); + # ifdef IPCS_SYSV // SystemV # ifndef OS2 // Il faut commencer par éliminer le sémaphore. @@ -2932,6 +3224,16 @@ destruction_queue_signaux(struct_process } unlink((*s_queue_signaux).semaphore.path); + free((*s_queue_signaux).semaphore.path); + + if (semctl((*s_queue_signaux).signalisation.sem, 0, IPC_RMID) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_processus; + return; + } + + unlink((*s_queue_signaux).signalisation.path); + free((*s_queue_signaux).signalisation.path); if (shmdt(s_queue_signaux) == -1) { @@ -2958,6 +3260,9 @@ destruction_queue_signaux(struct_process sem_close(&((*s_queue_signaux).semaphore)); sem_destroy(&((*s_queue_signaux).semaphore)); + sem_close(&((*s_queue_signaux).signalisation)); + sem_destroy(&((*s_queue_signaux).signalisation)); + if (DosFreeMem(s_queue_signaux) != 0) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; @@ -2968,9 +3273,15 @@ destruction_queue_signaux(struct_process # ifndef SEMAPHORES_NOMMES sem_close(&((*s_queue_signaux).semaphore)); sem_destroy(&((*s_queue_signaux).semaphore)); + + sem_close(&((*s_queue_signaux).signalisation)); + sem_destroy(&((*s_queue_signaux).signalisation)); # else sem_close(semaphore_queue_signaux); sem_destroy2(semaphore_queue_signaux, getpid(), SEM_QUEUE); + + sem_close(semaphore_signalisation); + sem_destroy2(semaphore_signalisation, getpid(), SEM_SIGNALISATION); # endif if (munmap(s_queue_signaux, sizeof(struct_queue_signaux)) != 0)