IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Comportement étrange après le chargement d'une bibliothèque dynamique


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut Comportement étrange après le chargement d'une bibliothèque dynamique
    Bonjour à tous,

    J'ai réalisé un programme qui fait appel à des librairies chargé dynamiquement via dlopen, lors de l' execution du symbole "module_init" recupéré via dlsym mon module fait appel a une commande interne du programme principal qui me remplie une structure de type command_t et ajoute l'element dans un tableau, jusqu'ici tout semble bien aller sauf que lorsque je parcours le tableau pour vérifier que mon pointeur s'y trouve bien et bien il n'y est pas !? Je me dit encore une ânerie de ma part mais lorsqu'a la fin de mon programme je veux décharger mon module via dlsym (... "module_end") et donc au passage libérer mon tableau (je le parcours de nouveau) et bien la mon element de type command_t est bien la, je ne sais même pas comment vous exposer explicitement mon problème tellement celui me depasse.

    Je suis sous windows 7 et j'utilise cygwin32 pour compiler le programme

    Le Makefile compilant les sources:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    CC      = gcc
    CFLAGS  = -Wall -O -Wpadded -I /home/blackbox/havoc-ircd/include 
    LDFLAGS = -Wall -Wl,--export-all-symbols -ldl
    SRCS    = $(wildcard *.c)
    OBJS    = $(SRCS:.c=.o)
     
    all: $(OBJS)
    	@$(CC) $(CFLAGS) $(LDFLAGS) -o ircd.exe $(OBJS)  
    	@mv -f ircd.exe ..
     
    %.o: %.c
    	@echo -e "BUILD: $@ from $<"
    	@$(CC) $(CFLAGS) -c $<  
     
    clean:
    	@echo -e "Clearing /home/blackbox/havoc-ircd/src objects ..."
    	@rm -f *.o
    	@cd .. && rm ircd.exe
    Le Makefile compilant mes modules:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    CC      = gcc
    CFLAGS  = -Wall -g -Wpadded -I /home/blackbox/havoc-ircd/include 
    LDFLAGS = -shared 
    SRCS    = $(wildcard *.c)
    OBJS    = $(wildcard /home/blackbox/havoc-ircd/src/*.o)
    SOBJS   = $(SRCS:.c=.so)
     
    all: $(SOBJS)
     
    %.so: %.c
    	@echo -e "BUILD: $@ from $<"
    	@$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(OBJS)
     
     
    clean:
    	@echo -e "Clearing /home/blackbox/havoc-ircd/src/commands shared objects ..."
    	@rm -f *.so
    Le fichier module.c ou les actions dlopen/dlsym et dlclose se trouvent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    #include "module.h"
     
     
    static module_t *modlist[MODHASHSIZE] = {0};
     
     
    static unsigned int modhash(const char *str)
    {
    	unsigned int hash = 0;
    	int c;
     
    	while ((c = *str++))
    	    hash += c;
     
    	return (hash & (MODHASHSIZE - 1));
    }
     
     
    int load_module(const char *filename)
    {
    	void *handle;
    	void (*func) (void);
    	char *error = NULL;
    	//char name[KEYLEN + 1];
    	module_t *new = NULL;
    	unsigned int hash;
     
    	if (find_module(filename)) /* module deja chargé, rien a faire */
    		return 1;
     
    	if (!(handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL)))
    	{
    		printf("load_module 2 %s (%s) %p\n", filename, dlerror(), handle);
    		return 0;
    	}
     
    	dlerror(); /* clear olders errors */
     
    	func = dlsym(handle, "module_init");
    	if ((error = dlerror()) != NULL)
    	{
    		printf("load_module 3 %s\n", filename);
    		dlclose(handle);
    		return 0;
    	}
     
    	if (!func) return 0;
     
    	if (!(new = calloc(1, sizeof(*new))))
    	{
    		printf("load_module: malloc failed\n");
    		return 0;
    	}
     
    	hash = modhash(filename);
    	strncpy(new->name, filename, FILELEN);
    	new->handle = handle;
    	printf("[+MODULE]: name=%s address=%p table location=%i\n", new->name, new, hash);
     
    	new->next = modlist[hash];
    	modlist[hash] = new;
    	func();
    	return 1;
    }
     
     
    module_t *find_module(const char *name)
    {
    	module_t *mod = modlist[modhash(name)];
    	for (; mod && strcasecmp(name, mod->name); mod = mod->next);
    	return mod;
    }
     
     
    void unload_module(module_t *mod)
    {
    	char *error = NULL;
    	void (*func) (void);
     
    	func = dlsym(mod->handle, "module_end");
    	if ((error = dlerror()) != NULL && !func)
    	{
    		// erreur
    	}
    	else (*func)();
     
    	printf("[-MODULE]: name=%s address=%p table location=%i next=%s\n", mod->name, mod, modhash(mod->name), (mod->next) ? mod->next->name : "NULL");
    	dlclose(mod->handle);
    	modlist[modhash(mod->name)] = mod->next;
    	free(mod);
    }
     
     
    void close_modules(void)
    {
    	unsigned int i = 0;
    	for (; i < MODHASHSIZE; i++)
    	{
    		if (modlist[i])
    		{
    			unload_module(modlist[i]);
    		}
    	}
    }
    Le fichier command.c ou je créer les elements de type command_t
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #include "command.h"
     
     
    static command_t *cmdtable[CMDHASHSIZE] = {0};
     
     
    static unsigned int cmdhash(const char *str)
    {
    	unsigned int hash = 0;
     
    	while (*str)
    	{
    	    hash += (hash << 3) + tolower((unsigned char)*str++);
    	}
    	return (hash & (CMDHASHSIZE - 1));
    }
     
     
    static void add_cmdhash(command_t *cmd)
    {
    	unsigned int hashv = cmdhash(cmd->name);
     
    	cmd->next = cmdtable[hashv];
    	cmdtable[hashv] = cmd;
    }
     
     
    command_t *add_command(const char *name, unsigned int level, int (*handle) (connect_t *connect, int parc, char **parv))
    {
    	command_t *new = NULL;
     
    	if (!name || !*name)
    		return NULL;
     
    	if (find_command(name))
    		return NULL;
     
    	if ((new = calloc(1, sizeof(*new))) == NULL)
    		return NULL;
     
    	strncpy(new->name, name, COMLEN);
    	new->level = level;
    	new->handle = handle;
     
    	add_cmdhash(new);
    	printf("[+COMMAND]: name=%s address=%p table location=%i\n", new->name, new, cmdhash(new->name));
    	return new;
    }
     
     
    command_t *find_command(const char *name)
    {
    	unsigned int hashv = cmdhash(name);
    	command_t *cmd = cmdtable[hashv];
    	printf("[DEBUG] find_command(%s): cmdtable[%i]=%p\n", name, hashv, cmdtable[hashv]);
     
    	for (; cmd && strcasecmp(name, cmd->name); cmd = cmd->next);
    	return cmd;
    }
     
     
    void del_command(command_t *cmd)
    {
    	unsigned int hashv = cmdhash(cmd->name);
    	command_t *tmp = cmdtable[hashv];
     
    	if (tmp == cmd) cmdtable[hashv] = cmd->next;
    	else
    	{
    		for (; tmp && tmp->next != cmd; tmp = tmp->next);
    		if (tmp) tmp->next = cmd->next;
    	}
    	printf("[-COMMAND]: name=%s address=%p table location=%i next=%s\n", tmp->name, tmp, hashv, (tmp->next) ? tmp->next->name : "NULL");
    	free(cmd);
    }
    un module parmi d'autre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    #include "ircd.h"
     
     
    int cmd_nick(connect_t *, int, char **);
     
     
    void module_init(void)
    {
    	add_command("NICK", 0, cmd_nick);
    }
     
     
    void module_end(void)
    {
    	command_t *cmd = find_command("NICK");
     
    	if (cmd) del_command(cmd);
    }
     
     
    static int validnick(const char *nick)
    {
    	return 1;
    }
     
     
    int cmd_nick(connect_t *connect, int parc, char **parv)
    {
    	/* nouveau client entreprend son identification */
    	if (IsConnect(connect))
    	{
    		if ((parc < 1) || !validnick(parv[0]))
    			del_connect(connect);
     
    		connect->type = TP_CLIENT;
    		strncpy(connect->nick, parv[0], NICKLEN);
    		printf("NICK merge: %s\n", connect->nick);
    	}
     
    	/* changement de pseudonyme */
    	else if (IsClient(connect))
    	{
    		if (parc < 1)
    			return send_numeric(connect, ERR_NONICKNAMEGIVEN, connect->nick);
     
    		if (!strcasecmp(connect->nick, parv[0]))
    			return 0;
     
    		if (!validnick(parv[0]))
    			return send_numeric(connect, ERR_ERRONEOUSNICKNAME, me->name, connect->nick, parv[0], "Pseudonyme erroné");
    	}
    	return 0;
    }
    et voici le résultat en console
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    blackbox@blackbox-PC ~/havoc-ircd
    $ ./ircd.exe
    [+MODULE]: name=/home/blackbox/havoc-ircd/src/commands/cmd_nick.so address=0x80040250 table location=11
    [DEBUG] find_command(NICK): cmdtable[93]=0x0                                            /* ici la commande n'est pas encore créer mais je verifie qu'elle ne le soit pas déja */
    [+COMMAND]: name=NICK address=0x80050300 table location=93                      /* elle ne l'ete pas donc création ... */
    [+CONNECTION] 192.168.1.39:64948 fd=4 highest_fd: 4                                   /* un client se connecte */
    Traffic from fd=4 bytes=52 data=NICK newbie                                                 /* il envoi une requete de commande NICK, crée précédement */
    [DEBUG] find_command(NICK): cmdtable[93]=0x0                                            /* je verifie que cette commande existe et bien non sa position dans le tableau NULL */
    Traffic from fd=4 bytes=52 data=USER kvirc 0 192.168.1.39 :Lil Chapdo
    [DEBUG] find_command(USER): cmdtable[15]=0x0
    received SIGINT/SIGTERM - closing link                                                          /* j'interromps le programme manuellement et decharge les modules */
    accept: 11 Resource temporarily unavailable
    [DEBUG] find_command(NICK): cmdtable[93]=0x80050300                                 /* et la c'est le bug de l'an 2000 ? WTF ???? */
    [-COMMAND]: name=NICK address=0x80050300 table location=93 next=NULL
    [-MODULE]: name=/home/blackbox/havoc-ircd/src/commands/cmd_nick.so address=0x80040250 table location=11 next=NULL
    closing: 4
    closing: 3

    Aucune erreur à la compilation, le programme s'execute correctement, les autres actions à réaliser après un chargement de module fonctionne (creation socket, ecoute du traffic, etc ...)
    En gros entre l'appel à module_init et module_end mon tableau cmdtable est NULL.

    Désolé du pavé que je viens de balancer, si jamais quelqu'un a envie de se ronger le cerveau avec moi je suis preneur, je tiens à préciser que je ne t'attend qu'on me serve la réponse sur un plateau je suis cloué sur le problème depuis déja presqu'un mois j'ai mangé le man de gcc, ld , dlopen et co, essayé des trucs plus ou moins censé d'autres pas du tout et la je séche totalement ...

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    curieux en effet, des pistes :
    • La cmdTable est déclarée static. On n'est pas dans un .h. Essaye de lever static pour voir s'il n'y en a pas deux
    • N'y a-t-il pas plusieurs process? des fork() ou des spawn() nous feraient voir des espaces mémoires différents

    D'autre part, ligne 100 de module.c, seul le 1er hash est détruit. Je mettrais plutôt while (modlist[i]) à la place de if (modlist[i])

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    Bonjour et merci d'avoir prit le temps de jeter un coup d'oeil, j'ai aussi essayé de déclarer cmdtable en extern, non static , le déclarer dans le fichier main et sans succès.
    Je n'utilise pas fork() ni autre dans le programme, j'ai aussi pensé a un problème d'espaces memoire different, le programme et la librairie ne partage peut être pas le même espace vu qu'elle est chargé ultérieurement ? Dans le fichier module ligne 100 je parcours déja le tableau via for() .

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par Ganondorf Voir le message
    Dans le fichier module ligne 100 je parcours déja le tableau via for() .
    Oui, mais s'il y en a plusieurs pour un même hash code, il me semble que seul le premier de chaque hash sera libéré.

    Une librairie même si elle est dynamique est toujours dans le même espace que son client, c'est là son avantage.
    Curieux, tout se passe comme s'il y avait deux contextes.

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    Bonjour,

    Après maintes recherche toujours rien, est-il possible que ça soit une erreur de compilation ? Parcqu'avant je faisais tourner ce code sous linux sans soucis, sauf que pour la compilation des modules, je n'avais pas a inclure les fichiers sources du programme (juste les headers) comme je suis obligé de le faire sous cygwin qui me gratifie d'un undefined reference vers ... si je ne les inclus pas.

    sous linux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    %.so: %.c
    	@echo -e "BUILD: $@ from $<"
    	@$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
    sous cygwin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    %.so: %.c
    	@echo -e "BUILD: $@ from $<"
    	@$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(OBJS)

Discussions similaires

  1. [XL-2010] Comportement étrange après ouverture d'image sur visionneuse à partir d'un formulaire
    Par OursTortue dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 02/10/2015, 12h34
  2. Créer une bibliothèque dynamique
    Par sinfoni dans le forum C
    Réponses: 0
    Dernier message: 27/03/2012, 09h55
  3. comportement étrange après installation
    Par eridan26 dans le forum Bubuntu
    Réponses: 2
    Dernier message: 21/05/2008, 22h48
  4. chargement d'une librairie dynamique
    Par ltournayre dans le forum C
    Réponses: 11
    Dernier message: 29/09/2006, 17h11
  5. Comportement étrange apres une désinstallation
    Par Sunchaser dans le forum Excel
    Réponses: 4
    Dernier message: 06/08/2005, 19h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo