Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Truc bizarre avec la libc

6 views
Skip to first unread message

JKB

unread,
Apr 1, 2009, 11:12:19 AM4/1/09
to
Bonjour à tous,

Je développe un gros programme massivement multithreadé sur une
debian/squeeze à jour (glibc 2.9 et noyau 2.6.28 compilé par mes soins,
le tout sur un core2duo en distribution amd64).

Mon programme bloque aléatoirement dans un mutex interne à la libc,
précisément dans l'appel free(). Lorsqu'il bloque, c'est toujours lors
du même free(), mais jamais à la même itération. Comme ce genre de
dysfonctionnement provient généralement d'une corruption du tas, j'ai
bissecté le programme dans tous les sens et débuggué avec valgrind,
_MEMCHECK=3, efence (au passage joyeusement buggué en environnement
multithread...) et quelques autres. Je puis assurer que mon programme ne
comporte aucune corruption mémoire et que le pointeur à libérer contient
bien la bonne chose. Il va sans dire que le programme en question est
compilé avec -D_REENTRANT et la libpthread (posix).

Mes constatations :
1/ en lançant le programme directement, il bloque une fois sur deux. Il
bloque lors de la réception par ce thread d'un signal demandant un arrêt
anticipé (un pthread_kill() qui va bien). Ce signal est bien reçu et
traité (sinon, le thread n'essayerait pas de s'arrêter). J'ai bien
validé que le signal était reçu par le bon thread et traité. Le
gestionnaire de signal en question se contente de positionner une valeur
entière atomique dans une variable volatile ;
2/ en le lançant avec un quelconque débuggueur mémoire, il va jusqu'au
bout et je n'ai jamais réussi à provoquer une condition bloquante.

Ce problème ne provient pas d'une condition de timing puisque le
free() bloquant est un free() effectué juste avant le pthread_exit()
pour libérer la structure passer en argument au thread. J'ai par
ailleurs vérifié toutes les conditions de temps sur tous mes mutexes et
tous mes signaux. Aucun ne peut bloquer indéfiniment.

Ce matin, en essayant de remplacer la libc par la même libc mais compilée
par mes soins (enfin, par mon gcc, mais avec toutes les options de
compilation qui vont bien pour avoir les symboles de débogage _et_ les
sources), j'ai fait méchamment planter ma machine. Je l'ai donc rebootée
dans la _même_ configuration que précédemment. Depuis, il m'est
_impossible_ de reproduire le bug. Il n'y a à cela aucune raison
rationnelle.

Entre le dernier reboot volontaire et mon plantage de ce matin, il y
a eu un passage de la glibc 2.7 vers la 2.9 (sans reboot). Est-ce que
cela pourrait être à l'origine de mon problème, et si oui, pourquoi ?
Quel est le rapport entre la réception d'un signal (en l'occurrence
SIGUSR1) et ce mutex interne ? Et pourquoi _ce_ mutex à la fin du thread
? Il y a une palanquée de free() entre le traitement du signal SIGUSR1
et la fin du thread (plusieurs centaines de Mo de mémoire à libérer).
Pour ceux que ça intéresse, il s'agit du mutex verrouillé à la ligne
3623 du fichier malloc.c du répertoire malloc de la glibc 2.9. Je sèche
et je n'aime pas ne pas comprendre...

Merci de vos lumières,

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.

0 new messages