J'ai un petit problème avec un code écrit en C et utilisant les
threads POSIX. Je poste ici parce que j'ai déjà vu le problème sous
Solaris (résolu il me semble avec l'utilisation de la libmtmalloc en
lieu et place des malloc() et free() de la libc). J'observe maintenant
quelque chose de semblable sous Linux et ça m'inquiète.
De temps en temps, j'ai un free() tout bête qui bloque dans une
section protégée par un mutex. J'avoue ne vois pas trop savoir pourquoi.
Comme le mutex est verrouillé, les autres threads attendent sa
libération qui n'intervient jamais puisque le programme reste bloqué
dans ce free().
Là, ça vient de bloquer dans le free(l_element_courant), juste avant
la libération du mutex. Celui-ci est déclaré de manière statique avec
la valeur PTHREAD_MUTEX_INITIALIZER. Les listes chaînées sont des
structures contenant deux champs, un void *donnee et un pointeur suivant
sur le maillon suivant.
if (pthread_mutex_unlock(&mutex_liste_threads) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
return;
}
Quelques sorties de gdb :
(gdb) backtrace
#0 0x00007fff39384cfe in ?? () from /lib/libc.so.6
#1 0x00007fff3932264e in ?? () from /lib/libc.so.6
#2 0x00007fff3931eceb in free () from /lib/libc.so.6
#3 0x000000000056096a in retrait_thread_surveillance (
s_etat_processus=0x7fff43909b20, s_argument_thread=0x7fff2c007cb0)
at interruptions.conv.c:248
#4 0x00000000004630ed in surveillance_processus (argument=0x7fff2c007cb0)
at gestion_processus.conv.c:1664
#5 0x00007fff3a185faa in start_thread () from /lib/libpthread.so.0
#6 0x00007fff393792cd in clone () from /lib/libc.so.6
Il va sans dire que j'ai vérifié la validité du pointeur (qui ne
peut être libéré que dans cette routine, c'est facile à vérifier,
d'autant plus que la racine de la liste est déclarée statique à ce
fichier). Rien n'est relevé par valgrind. Les valeurs des pointeurs
sont :
ce qui n'est pas aberrant. La question de fond est donc : qu'est-ce qui
pourrait bien faire qu'un free() bloque ? Si le pointeur passé en
argument était invalide, à la rigueur, je comprendrais. Mais là, le
free() bloque sur un pointeur parfaitement valide !
Je prends tout début d'explication. Est-ce que la définition de
_REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
fichiers d'en-tête qui pourrait me le faire croire et l'erreur en
question est _vraiment_ difficile à reproduire...
Cordialement,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Xavier Roche
JKB a écrit :
Je prends tout début d'explication. Est-ce que la définition de _REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Je prends tout début d'explication. Est-ce que la définition de
_REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain
nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui
nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Je prends tout début d'explication. Est-ce que la définition de _REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Le 27-03-2009, ? propos de Re: Threads POSIX et free(), Xavier Roche ?crivait dans fr.comp.lang.c :
JKB a écrit :
Je prends tout début d'explication. Est-ce que la définition de _REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Merci pour l'explication, mais il me semblait que c'était automatique avec les dernières version de gcc. Je vais donc essayer avec ça. Néanmoins, je viens de passer une bonne partie de la journée à regarder ce que fait free(). Le truc bloque toujours aléatoirement sur le pthread_mutex_lock() interne à la fonction free() de la glibc. Pourtant, je fais tourne en parallèle ce code depuis quelques heures sous valgrind sans que celui-ci ne râle sur une corruption mémoire (je n'en ai pas trouvé non plus à la main...). Je continue la recherche et si je trouve, je vous tiendrai au courant ;-)
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.
Le 27-03-2009, ? propos de
Re: Threads POSIX et free(),
Xavier Roche ?crivait dans fr.comp.lang.c :
JKB a écrit :
Je prends tout début d'explication. Est-ce que la définition de
_REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain
nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui
nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Merci pour l'explication, mais il me semblait que c'était
automatique avec les dernières version de gcc. Je vais donc essayer avec
ça. Néanmoins, je viens de passer une bonne partie de la journée à
regarder ce que fait free(). Le truc bloque toujours aléatoirement sur
le pthread_mutex_lock() interne à la fonction free() de la glibc.
Pourtant, je fais tourne en parallèle ce code depuis quelques heures
sous valgrind sans que celui-ci ne râle sur une corruption mémoire (je
n'en ai pas trouvé non plus à la main...). Je continue la recherche et
si je trouve, je vous tiendrai au courant ;-)
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Le 27-03-2009, ? propos de Re: Threads POSIX et free(), Xavier Roche ?crivait dans fr.comp.lang.c :
JKB a écrit :
Je prends tout début d'explication. Est-ce que la définition de _REENTRANT pourrait corriger le problème ? Je n'ai rien trouvé dans les
Toujours utiliser -D_REENTRANT en multithreadé ; cela impacte un certain nombre de fonctions qui sinon ne sont pas thread-safe (tout ce qui nécessite des variables de thread, comme gmtime() par exemple, ou errno)
Merci pour l'explication, mais il me semblait que c'était automatique avec les dernières version de gcc. Je vais donc essayer avec ça. Néanmoins, je viens de passer une bonne partie de la journée à regarder ce que fait free(). Le truc bloque toujours aléatoirement sur le pthread_mutex_lock() interne à la fonction free() de la glibc. Pourtant, je fais tourne en parallèle ce code depuis quelques heures sous valgrind sans que celui-ci ne râle sur une corruption mémoire (je n'en ai pas trouvé non plus à la main...). Je continue la recherche et si je trouve, je vous tiendrai au courant ;-)
JKB
-- Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre masse corporelle, mais disperse à lui seul 25% de l'énergie que nous consommons tous les jours.