--- rpl/src/gestion_objets.c 2010/04/17 18:57:35 1.10 +++ rpl/src/gestion_objets.c 2010/06/09 12:18:17 1.25 @@ -1,6 +1,6 @@ /* ================================================================================ - RPL/2 (R) version 4.0.14 + RPL/2 (R) version 4.0.16 Copyright (C) 1989-2010 Dr. BERTRAND Joël This file is part of RPL/2. @@ -877,12 +877,21 @@ liberation(struct_processus *s_etat_proc { if (decrementation_atomique(s_objet) > 0) { + BUG((*(*((struct_fichier *) (*s_objet).objet)).format) + .nombre_occurrences <= 1, + pthread_mutex_unlock(&((*s_objet).mutex)), + printf("(*(*((struct_fichier *) (*s_objet).objet))" + ".format).nombre_occurrences=%ld\n", + (*(*((struct_fichier *) (*s_objet).objet)).format) + .nombre_occurrences)); + + liberation(s_etat_processus, + (*((struct_fichier *) (*s_objet).objet)).format); return; } liberation(s_etat_processus, (*((struct_fichier *) (*s_objet).objet)).format); - free((unsigned char *) (*((struct_fichier *) (*s_objet).objet)).nom); free((struct_fichier *) ((*s_objet).objet)); @@ -1112,7 +1121,8 @@ liberation(struct_processus *s_etat_proc .nombre_references--; BUG((*(*((struct_processus_fils *) (*s_objet).objet)).thread) - .nombre_references < 0, printf("(*(*((struct_processus_fils" + .nombre_references < 0, uprintf( + "(*(*((struct_processus_fils" " *) (*s_objet).objet)).thread).nombre_references = %d\n", (int) (*(*((struct_processus_fils *) (*s_objet).objet)) .thread).nombre_references)); @@ -1208,11 +1218,22 @@ liberation(struct_processus *s_etat_proc { if (decrementation_atomique(s_objet) > 0) { + BUG((*(*((struct_socket *) (*s_objet).objet)).format) + .nombre_occurrences <= 1, + pthread_mutex_unlock(&((*s_objet).mutex)), + printf("(*(*((struct_socket *) (*s_objet).objet))" + ".format).nombre_occurrences=%ld\n", + (*(*((struct_socket *) (*s_objet).objet)).format) + .nombre_occurrences)); + + liberation(s_etat_processus, (*((struct_socket *) + (*s_objet).objet)).format); return; } liberation(s_etat_processus, (*((struct_socket *) (*s_objet).objet)).format); + free((unsigned char *) (*((struct_socket *) (*s_objet).objet)) .adresse); free((unsigned char *) (*((struct_socket *) (*s_objet).objet)) @@ -1749,6 +1770,14 @@ copie_objet(struct_processus *s_etat_pro if (type == 'P') { incrementation_atomique(s_objet); + + if (((*((struct_fichier *) ((*s_objet).objet))).format = + copie_objet(s_etat_processus, (*((struct_fichier *) + ((*s_objet).objet))).format, 'P')) == NULL) + { + return(NULL); + } + return(s_objet); } @@ -2239,6 +2268,7 @@ copie_objet(struct_processus *s_etat_pro (*((struct_processus_fils *) (*s_nouvel_objet).objet)) = (*((struct_processus_fils *) (*s_objet).objet)); + break; } @@ -2265,6 +2295,15 @@ copie_objet(struct_processus *s_etat_pro if (type == 'P') { incrementation_atomique(s_objet); + + if (((*((struct_socket *) ((*s_objet).objet))) + .format = copie_objet(s_etat_processus, + (*((struct_socket *) ((*s_objet).objet))).format, 'P')) + == NULL) + { + return(NULL); + } + return(s_objet); } @@ -2762,6 +2801,8 @@ copie_etat_processus(struct_processus *s (*s_nouvel_etat_processus).nombre_interruptions_en_queue = 0; (*s_nouvel_etat_processus).nombre_interruptions_non_affectees = 0; + (*s_nouvel_etat_processus).at_exit = NULL; + for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++) { (*s_nouvel_etat_processus).corps_interruptions[i] = NULL; @@ -3041,6 +3082,8 @@ copie_etat_processus(struct_processus *s (*s_etat_processus).s_liste_variables[i].niveau; (*s_nouvel_etat_processus).s_liste_variables[i].variable_statique = (*s_etat_processus).s_liste_variables[i].variable_statique; + (*s_nouvel_etat_processus).s_liste_variables[i].variable_partagee = + (*s_etat_processus).s_liste_variables[i].variable_partagee; (*s_nouvel_etat_processus).s_liste_variables[i].variable_verrouillee = (*s_etat_processus).s_liste_variables[i].variable_verrouillee; @@ -3524,16 +3567,23 @@ copie_etat_processus(struct_processus *s #undef malloc #undef realloc #undef free +#undef fork #ifdef return # undef return #endif -#undef fprintf - +#ifdef __BACKTRACE +#define PROFONDEUR_PILE 64 #define return(a) { if (a == NULL) \ - { BACKTRACE(20); fprintf(stderr, ">>> MEDITATION %d\n", __LINE__); } \ + { BACKTRACE(PROFONDEUR_PILE); \ + fprintf(stderr, ">>> MEDITATION %d\n", __LINE__); } \ return(a); } while(0) +#endif + +#undef fprintf +#define check(a, b) ((strcmp(#a, fonction) == 0) && (ligne == b)) +#undef CORE_DUMP typedef struct memoire { @@ -3543,14 +3593,29 @@ typedef struct memoire unsigned long ligne; size_t taille; unsigned long long ordre; +# ifdef __BACKTRACE + void *pile[PROFONDEUR_PILE]; + int profondeur; +# endif struct memoire *suivant; } struct_memoire; static struct_memoire *debug = NULL; static unsigned long long ordre = 0; -static pthread_mutex_t mutex_allocation = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_allocation; -#define check(a, b) ((strcmp(#a, fonction) == 0) && (ligne == b)) +void +debug_memoire_initialisation() +{ + pthread_mutexattr_t attributs_mutex; + + pthread_mutexattr_init(&attributs_mutex); + pthread_mutexattr_settype(&attributs_mutex, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex_allocation, &attributs_mutex); + pthread_mutexattr_destroy(&attributs_mutex); + + return; +} void * debug_memoire_ajout(size_t taille, const unsigned char *fonction, @@ -3558,6 +3623,8 @@ debug_memoire_ajout(size_t taille, const { struct_memoire *ancienne_base; + void *pointeur; + pthread_mutex_lock(&mutex_allocation); ancienne_base = debug; @@ -3579,26 +3646,35 @@ debug_memoire_ajout(size_t taille, const (*debug).taille = taille; (*debug).ordre = ordre; - pthread_mutex_unlock(&mutex_allocation); + pointeur = (*debug).pointeur; + +# ifdef __BACKTRACE + (*debug).profondeur = backtrace((*debug).pile, PROFONDEUR_PILE); +# endif if (((*debug).fonction = malloc((strlen(fonction) + 1) * sizeof(unsigned char))) == NULL) { + pthread_mutex_unlock(&mutex_allocation); return(NULL); } if (((*debug).argument = malloc((strlen(argument) + 1) * sizeof(unsigned char))) == NULL) { + pthread_mutex_unlock(&mutex_allocation); return(NULL); } strcpy((*debug).fonction, fonction); strcpy((*debug).argument, argument); + memset((*debug).pointeur, 0, (*debug).taille); + + pthread_mutex_unlock(&mutex_allocation); ordre++; - return((*debug).pointeur); + return(pointeur); } void * @@ -3612,9 +3688,11 @@ debug_memoire_modification(void *pointeu { if (taille == 0) { - // Revient à free() + // Revient à free(). Il n'y a pas de parenthèses car on ne veut + // pas utiliser la macro return(). + debug_memoire_retrait(pointeur); - return(NULL); + return NULL ; } else { @@ -3637,38 +3715,50 @@ debug_memoire_modification(void *pointeu if (element_courant == NULL) { pthread_mutex_unlock(&mutex_allocation); - return(NULL); - } - pthread_mutex_unlock(&mutex_allocation); + uprintf("[%d-%llu] ILLEGAL POINTER\n", + getpid(), (unsigned long long) pthread_self()); +# ifdef __BACKTRACE + BACKTRACE(PROFONDEUR_PILE); +# endif - if (((*element_courant).pointeur = realloc(pointeur, taille)) - == NULL) - { - return(NULL); + return(realloc(pointeur, taille)); } + else + { + if (((*element_courant).pointeur = realloc(pointeur, taille)) + == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } - (*element_courant).ligne = ligne; - (*element_courant).taille = taille; - free((*element_courant).fonction); - free((*element_courant).argument); + (*element_courant).ligne = ligne; + (*element_courant).taille = taille; + free((*element_courant).fonction); + free((*element_courant).argument); - if (((*element_courant).fonction = malloc((strlen(fonction) + 1) * - sizeof(unsigned char))) == NULL) - { - return(NULL); - } + if (((*element_courant).fonction = malloc((strlen(fonction) + + 1) * sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } - if (((*element_courant).argument = malloc((strlen(argument) + 1) * - sizeof(unsigned char))) == NULL) - { - return(NULL); - } + if (((*element_courant).argument = malloc((strlen(argument) + + 1) * sizeof(unsigned char))) == NULL) + { + pthread_mutex_unlock(&mutex_allocation); + return(NULL); + } - strcpy((*element_courant).fonction, fonction); - strcpy((*element_courant).argument, argument); + strcpy((*element_courant).fonction, fonction); + strcpy((*element_courant).argument, argument); - return((*element_courant).pointeur); + pthread_mutex_unlock(&mutex_allocation); + + return((*element_courant).pointeur); + } } } else @@ -3703,6 +3793,11 @@ debug_memoire_retrait(void *pointeur) (*element_precedent).suivant = (*element_courant).suivant; } + if (pointeur != NULL) + { + memset(pointeur, 0, (*element_courant).taille); + } + free((*element_courant).fonction); free((*element_courant).argument); free(element_courant); @@ -3716,20 +3811,34 @@ debug_memoire_retrait(void *pointeur) pthread_mutex_unlock(&mutex_allocation); - free(pointeur); + if (element_courant == NULL) + { + uprintf("[%d-%llu] ILLEGAL POINTER\n", + getpid(), (unsigned long long) pthread_self()); +# ifdef __BACKTRACE + BACKTRACE(PROFONDEUR_PILE); +# endif + } + free(pointeur); return; } void -debug_memoire_verification(struct_processus *s_etat_processus) +debug_memoire_verification() { +# ifdef __BACKTRACE + char **appels; + + int j; +# endif + integer8 i; struct_memoire *element_courant; struct_memoire *element_suivant; - fprintf(stderr, "[%d-%llu] MEMORY LEAK\n", + fprintf(stderr, "[%d-%llu] LIST OF MEMORY LEAKS\n", getpid(), (unsigned long long) pthread_self()); pthread_mutex_lock(&mutex_allocation); @@ -3751,31 +3860,109 @@ debug_memoire_verification(struct_proces (unsigned long long) pthread_self(), (*element_courant).argument); - switch(i) + if (strstr((*element_courant).argument, "sizeof(unsigned char)") + != NULL) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: %s\n", (unsigned char *) + (*element_courant).pointeur); + } + else if (strcmp((*element_courant).argument, "sizeof(struct_objet)") + == 0) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: %d\n", (*((struct_objet *) + (*element_courant).pointeur)).type); + } + else if (strcmp((*element_courant).argument, + "sizeof(struct_liste_chainee)") == 0) + { + fprintf(stderr, "[%d-%llu] ", getpid(), + (unsigned long long) pthread_self()); + fprintf(stderr, "O: data=%p next=%p\n", (*((struct_liste_chainee *) + (*element_courant).pointeur)).donnee, + (*((struct_liste_chainee *) (*element_courant).pointeur)) + .suivant); + } + +# ifdef __BACKTRACE + appels = backtrace_symbols((*element_courant).pile, + (*element_courant).profondeur); + + fprintf(stderr, "[%d-%llu] BACKTRACE\n", + getpid(), (unsigned long long) pthread_self()); + + if (appels != NULL) { - // Affichage des méditations - case 1: + for(j = 0; j < (*element_courant).profondeur; j++) { - break; + fprintf(stderr, "[%d-%llu] %s\n", getpid(), + (unsigned long long) pthread_self(), appels[j]); } + + free(appels); } +# endif + + fprintf(stderr, "\n"); i++; element_suivant = (*element_courant).suivant; + +# ifndef CORE_DUMP free((*element_courant).fonction); free((*element_courant).argument); free(element_courant); +# endif + element_courant = element_suivant; } pthread_mutex_unlock(&mutex_allocation); + pthread_mutex_destroy(&mutex_allocation); fprintf(stderr, "[%d-%llu] END OF LIST\n", getpid(), (unsigned long long) pthread_self()); return; } + +pid_t +debug_fork() +{ + pid_t pid; + + pthread_mutex_lock(&mutex_allocation); + pid = fork(); + + if (pid == 0) + { + pthread_mutex_destroy(&mutex_allocation); + debug_memoire_initialisation(); + } + else + { + pthread_mutex_unlock(&mutex_allocation); + } + + // Pas de parenthèses pour ne pas remplacer return par sa macro. + return pid; +} + +void +analyse_post_mortem() +{ +# ifdef CORE_DUMP + BUG(debug != NULL, uprintf("[%d-%llu] CREATE CORE DUMP FILE FOR " + "POST MORTEM ANALYZE\n", getpid(), + (unsigned long long) pthread_self())); +# endif + + return; +} #endif