Subject: libc6: strerror_r() not thread-safe Package: libc6 Version: 2.7-4 Severity: important Hello, strerror_r() crashes pseudo-randomly when multiple threads invoke it simultaneously. It appears the problem never occurs when using the C/POSIX locale, and seems to be gettext-related. Test code attached. Interestingly, I once had the crash with the first error message in C locale: # ./a.out Connection timed out Erreur de segmentation # Then again, I also had this once: # ./a.out Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Connexion terminée par expiration du délai d'attente Erreur de segmentation # Could not reproduce under valgrind - still from gdb: # gdb ./a.out (...) (gdb) run (...) Connexion terminée par Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x86bd0b90 (LWP 10614)] 0xb7e599d8 in strcmp () from /lib/i686/cmov/libc.so.6 (gdb) bt #0 0xb7e599d8 in strcmp () from /lib/i686/cmov/libc.so.6 #1 0xb7e0d473 in _nl_find_msg () from /lib/i686/cmov/libc.so.6 #2 0xb7e0e122 in __dcigettext () from /lib/i686/cmov/libc.so.6 #3 0xb7e0ceb3 in dcgettext () from /lib/i686/cmov/libc.so.6 #4 0xb7e59ee9 in strerror_r () from /lib/i686/cmov/libc.so.6 #5 0xb7e27c9f in vfprintf () from /lib/i686/cmov/libc.so.6 #6 0xb7e4a874 in vsnprintf () from /lib/i686/cmov/libc.so.6 #7 0xb7e2f1d5 in snprintf () from /lib/i686/cmov/libc.so.6 #8 0x080485f0 in run () #9 0xb7f3a4fb in start_thread () from /lib/i686/cmov/libpthread.so.0 #10 0xb7ebe60e in clone () from /lib/i686/cmov/libc.so.6 -- System Information: Debian Release: lenny/sid APT prefers unstable APT policy: (100, 'unstable'), (100, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.23.8 (SMP w/2 CPU cores) Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages libc6 depends on: ii libgcc1 1:4.2.2-4 GCC support library libc6 recommends no packages. -- debconf information: glibc/restart-failed: glibc/restart-services: -- Rémi Denis-Courmont http://www.remlab.net/
#include <stdio.h> #include <pthread.h> #include <locale.h> #include <libintl.h> #include <errno.h> #define NTH 100 static pthread_barrier_t *bp; static void *run (void *dummy) { char buf[256]; (void)dummy; errno = ETIMEDOUT; pthread_barrier_wait (bp); for (;;) { snprintf (buf, sizeof (buf), "%m"); puts (buf); } } int main (void) { unsigned i; pthread_barrier_t barrier; pthread_t threads[NTH]; setlocale (LC_ALL, ""); bindtextdomain ("vlc", "/usr/share/locale"); pthread_barrier_init (&barrier, NULL, NTH); bp = &barrier; for (i = 0; i < NTH; i++) pthread_create (threads + i, NULL, run, NULL); run (NULL); return 0; }
Attachment:
signature.asc
Description: This is a digitally signed message part.