--- rpl/src/interruptions.c 2010/08/13 21:00:37 1.29 +++ rpl/src/interruptions.c 2010/08/17 11:59:28 1.30 @@ -1724,9 +1724,438 @@ deverrouillage_gestionnaire_signaux() return; } +#ifdef _BROKEN_SIGINFO + +static int *fifos; +static int segment; +static int segment_mutexes; +static int longueur_queue; +static int nombre_queues; + +static pthread_mutex_t *mutexes; + +static unsigned char *chemin = NULL; + +unsigned char * +nom_segment(unsigned char *chemin, pid_t pid) +{ + unsigned char *fichier; + + if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) * + sizeof(unsigned char))) == NULL) + { + return(NULL); + } + + sprintf(fichier, "%s/RPL-SIGQUEUES-%d", chemin, (int) pid); + + return(fichier); +} + +unsigned char * +nom_segment_mutexes(unsigned char *chemin, pid_t pid) +{ + unsigned char *fichier; + + if ((fichier = malloc((strlen(chemin) + 1 + 256 + 1) * + sizeof(unsigned char))) == NULL) + { + return(NULL); + } + + sprintf(fichier, "%s/RPL-SIGMUTEXES-%d", chemin, (int) pid); + + return(fichier); +} + +int +queue_de_signal(int signal) +{ + switch(signal) + { + case SIGINT: + return(0); + case SIGTSTP: + return(1); + case SIGCONT: + return(2); + case SIGURG: + return(3); + case SIGPIPE: + return(4); + case SIGALRM: + return(5); + case SIGFSTOP: + return(6); + case SIGSTART: + return(7); + case SIGINJECT: + return(8); + case SIGABORT: + return(9); + case SIGFABORT: + return(10); + } + + return(-1); +} + void -interruption1(int signal, siginfo_t *siginfo, void *context) +creation_fifos_signaux(struct_processus *s_etat_processus) { + file *desc; + + int i; + + key_t clef; + + pthread_mutexattr_t attributs_mutex; + + unsigned char *nom; + + /* + * Signaux utilisés + * SIGINT, SIGTSTP, SIGCONT, SIGURG, SIGPIPE, SIGALRM, SIGFSTOP, + * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT + */ + + // Création d'un segment de données associé au PID du processus courant + + chemin = (*s_etat_processus).chemin_fichiers_temporaires; + + if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires, + getpid())) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + /* + * Structure d'une queue + * 0 : pointeur en lecture sur le premier emplacement libre (int) + * 1 : pointeur en écriture sur le premier emplacement à lire (int) + * 2 : longueur de la queue (int) + * 3 : éléments restants (int) + * 4 à 4 + (2) : queue (int) + * 5 : mutex + */ + + nombre_queues = 11; + longueur_queue = 256; + + if ((desc = fopen(nom, "w")) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; + return; + } + + fclose(desc); + + if ((clef = ftok(nom, 1)) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + free(nom); + + if ((segment = shmget(clef, + nombre_queues * (longueur_queue + 4) * sizeof(int), + IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + fifos = shmat(segment, NULL, 0); + + if (((void *) fifos) == ((void *) -1)) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + for(i = 0; i < nombre_queues; i++) + { + fifos[(i * (longueur_queue + 4))] = 0; + fifos[(i * (longueur_queue + 4)) + 1] = 0; + fifos[(i * (longueur_queue + 4)) + 2] = longueur_queue; + fifos[(i * (longueur_queue + 4)) + 3] = longueur_queue; + } + + if ((nom = nom_segment_mutexes((*s_etat_processus) + .chemin_fichiers_temporaires, getpid())) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + if ((desc = fopen(nom, "w")) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; + return; + } + + fclose(desc); + + if ((clef = ftok(nom, 1)) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + free(nom); + + if ((segment_mutexes = shmget(clef, + nombre_queues * sizeof(pthread_mutex_t), + IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + mutexes = shmat(segment_mutexes, NULL, 0); + + if (((void *) mutexes) == ((void *) -1)) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + /* + * Création et initialisation d'un mutex par queue. Ce mutex n'est pas + * dans le premier segment parce qu'il peut y avoir des problèmes + * d'alignements sur certaines architectures. + */ + + pthread_mutexattr_init(&attributs_mutex); + pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_NORMAL); + + for(i = 0; i < nombre_queues; i++) + { + pthread_mutex_init(&(mutexes[i]), &attributs_mutex); + } + + pthread_mutexattr_destroy(&attributs_mutex); + return; +} + +void +liberation_fifos_signaux(struct_processus *s_etat_processus) +{ + if (shmdt(fifos) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + if (shmdt(mutexes) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + return; +} + +void +destruction_fifos_signaux(struct_processus *s_etat_processus) +{ + int i; + unsigned char *nom; + + if (shmdt(fifos) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + if (shmctl(segment, IPC_RMID, 0) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + for(i = 0; i < nombre_queues; i++) + { + pthread_mutex_destroy(&(mutexes[i])); + } + + if (shmdt(mutexes) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + if (shmctl(segment_mutexes, IPC_RMID, 0) == -1) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + if ((nom = nom_segment_mutexes((*s_etat_processus) + .chemin_fichiers_temporaires, getpid())) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + unlink(nom); + free(nom); + + if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires, + getpid())) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return; + } + + unlink(nom); + free(nom); + + return; +} + +int +queue_in(pid_t pid, int signal) +{ + int *base; + int *buffer; + int *projection_fifos; + int queue; + int identifiant; + + key_t clef; + + pthread_mutex_t *projection_mutexes; + + unsigned char *nom; + + queue = queue_de_signal(signal); + + // Ouverture des projections + + if ((nom = nom_segment(chemin, pid)) == NULL) + { + return(-1); + } + + if ((clef = ftok(nom, 1)) == -1) + { + free(nom); + return(-1); + } + + free(nom); + + while((identifiant = shmget(clef, + nombre_queues * (longueur_queue + 4) * sizeof(int), + S_IRUSR | S_IWUSR)) == -1); + + projection_fifos = shmat(identifiant, NULL, 0); + + if ((nom = nom_segment_mutexes(chemin, pid)) == NULL) + { + return(-1); + } + + if ((clef = ftok(nom, 1)) == -1) + { + free(nom); + return(-1); + } + + free(nom); + + while((identifiant = shmget(clef, + nombre_queues * sizeof(pthread_mutex_t), + S_IRUSR | S_IWUSR)) == -1); + + projection_mutexes = shmat(identifiant, NULL, 0); + + if (pthread_mutex_lock(&(projection_mutexes[queue])) != 0) + { + return(-1); + } + + base = &(projection_fifos[(longueur_queue + 4) * queue]); + buffer = &(base[4]); + + // base[1] contient le prochain élément à écrire + buffer[base[1]++] = (int) pid; + base[1] %= base[2]; + + // base[3] contient le nombre d'éléments non lus + if (base[3] <= 0) + { + pthread_mutex_unlock(&(projection_mutexes[queue])); + shmdt(projection_mutexes); + shmdt(projection_fifos); + return(-1); + } + + base[3]--; + + if (pthread_mutex_unlock(&(projection_mutexes[queue])) != 0) + { + shmdt(projection_mutexes); + shmdt(projection_fifos); + return(-1); + } + + // Fermeture des projections + shmdt(projection_mutexes); + shmdt(projection_fifos); + return(0); +} + +pid_t +origine_signal(int signal) +{ + int *base; + int *buffer; + int pid; + int queue; + + queue = queue_de_signal(signal); + + BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n", + (int) getpid(), signal)); + + if (pthread_mutex_lock(&(mutexes[queue])) != 0) + { + perror("lock"); + return(-1); + } + + base = &(fifos[(longueur_queue + 4) * queue]); + buffer = &(base[4]); + pid = buffer[base[0]++]; + base[0] %= base[2]; + base[3]++; + + if (base[3] > base[2]) + { + uprintf("Base\n"); + pthread_mutex_unlock(&(mutexes[queue])); + return(-1); + } + if (pthread_mutex_unlock(&(mutexes[queue])) != 0) + { + perror("unlock"); + return(-1); + } + + return((pid_t) pid); +} + +#endif + +void +interruption1(SIGHANDLER_ARGS) +{ + pid_t pid; + pthread_t thread; struct_processus *s_etat_processus; @@ -1734,7 +2163,9 @@ interruption1(int signal, siginfo_t *sig volatile sig_atomic_t exclusion = 0; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -1743,13 +2174,13 @@ interruption1(int signal, siginfo_t *sig { case SIGALRM : { - if ((*siginfo).si_pid == getpid()) + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) { deverrouillage_gestionnaire_signaux(); - return; + return; } if (((*s_etat_processus).type_debug & d_debug_signaux) != 0) @@ -1788,11 +2219,14 @@ interruption1(int signal, siginfo_t *sig * Solaris suit en particulier cette spécification. */ +# ifndef _BROKEN_SIGINFO if (siginfo == NULL) { kill(getpid(), signal); } - else if ((*siginfo).si_pid == getpid()) + else +# endif + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) @@ -1867,17 +2301,23 @@ interruption1(int signal, siginfo_t *sig } void -interruption2(int signal, siginfo_t *siginfo, void *context) +interruption2(SIGHANDLER_ARGS) { + pid_t pid; + pthread_t thread; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); +# ifndef _BROKEN_SIGINFO if (siginfo == NULL) { /* @@ -1895,7 +2335,9 @@ interruption2(int signal, siginfo_t *sig return; } } - else if ((*siginfo).si_pid == getpid()) + else +# endif + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) @@ -1943,14 +2385,18 @@ interruption2(int signal, siginfo_t *sig } void -interruption3(int signal, siginfo_t *siginfo, void *context) +interruption3(SIGHANDLER_ARGS) { + pid_t pid; + struct_processus *s_etat_processus; static int compteur = 0; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2007,12 +2453,16 @@ interruption3(int signal, siginfo_t *sig } void -interruption4(int signal, siginfo_t *siginfo, void *context) +interruption4(SIGHANDLER_ARGS) { + pid_t pid; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2039,18 +2489,23 @@ interruption4(int signal, siginfo_t *sig } void -interruption5(int signal, siginfo_t *siginfo, void *context) +interruption5(SIGHANDLER_ARGS) { + pid_t pid; + pthread_t thread; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); - if ((*siginfo).si_pid == getpid()) + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) @@ -2106,12 +2561,16 @@ interruption5(int signal, siginfo_t *sig } void -interruption6(int signal, siginfo_t *siginfo, void *context) +interruption6(SIGHANDLER_ARGS) { + pid_t pid; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2134,12 +2593,16 @@ interruption6(int signal, siginfo_t *sig } void -interruption7(int signal, siginfo_t *siginfo, void *context) +interruption7(SIGHANDLER_ARGS) { + pid_t pid; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2165,18 +2628,23 @@ interruption7(int signal, siginfo_t *sig } void -interruption8(int signal, siginfo_t *siginfo, void *context) +interruption8(SIGHANDLER_ARGS) { + pid_t pid; + pthread_t thread; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); - if ((*siginfo).si_pid == getpid()) + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) @@ -2212,12 +2680,16 @@ interruption8(int signal, siginfo_t *sig } void -interruption9(int signal, siginfo_t *siginfo, void *context) +interruption9(SIGHANDLER_ARGS) { + pid_t pid; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2236,21 +2708,35 @@ interruption9(int signal, siginfo_t *sig } deverrouillage_gestionnaire_signaux(); + +# ifdef _BROKEN_SIGINFO + if (queue_in(getpid(), signal) != 0) + { + return; + } + + interruption11(signal); +# else interruption11(signal, siginfo, context); +# endif return; } void -interruption10(int signal, siginfo_t *siginfo, void *context) +interruption10(SIGHANDLER_ARGS) { file *fichier; + pid_t pid; + struct_processus *s_etat_processus; unsigned char nom[8 + 64 + 1]; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); @@ -2286,18 +2772,23 @@ interruption10(int signal, siginfo_t *si } void -interruption11(int signal, siginfo_t *siginfo, void *context) +interruption11(SIGHANDLER_ARGS) { + pid_t pid; + pthread_t thread; + struct_processus *s_etat_processus; # ifdef _BROKEN_SIGINFO - (*siginfo).si_pid=getpid(); + pid = origine_signal(signal); +# else + pid = (*siginfo).si_pid; # endif verrouillage_gestionnaire_signaux(); - if ((*siginfo).si_pid == getpid()) + if (pid == getpid()) { if ((s_etat_processus = recherche_thread(getpid(), pthread_self())) == NULL) @@ -2375,4 +2866,45 @@ traitement_exceptions_gsl(const char *re return; } +#ifdef _BROKEN_SIGINFO + +#undef kill +#undef pthread_kill + +int +rpl_kill(pid_t pid, int signal) +{ + /* + * Lorsqu'on veut interrompre le processus pid, on ouvre le segment + * correspondant au processus en question et ou ajoute le pid dans la + * queue. + */ + + if (signal != 0) + { + if (queue_in(pid, signal) != 0) + { + return(-1); + } + } + + return(kill(pid, signal)); +} + +int +rpl_pthread_kill(pthread_t tid, int signal) +{ + if (signal != 0) + { + if (queue_in(getpid(), signal) != 0) + { + return(-1); + } + } + + return(pthread_kill(tid, signal)); +} + +#endif + // vim: ts=4