pthread_cond_broadcast cassé avec dlsym?

J’essaie d’interposer des appels à pthread_cond_broadcast à l’aide du mécanisme LD_PRELOAD. Ma fonction pthread_cond_broadcast interposée appelle simplement le pthread_cond_broadcast d’origine. Cependant, pour un code pthread très simple où pthread_cond_wait et pthread_cond_broadcast sont invoqués, je finis par obtenir un segfault dans glibc (pour glibc 2.11.1) ou le programme se bloque (pour glibc 2.15). Des indices sur ce qui se passe?

Le code d’interposition (compilé en tant que bibliothèque partagée):

#define _GNU_SOURCE #include  #include  #include  #include  static int (*orig_pthread_cond_broadcast)(pthread_cond_t *cond) = NULL; __atsortingbute__((constructor)) static void start() { orig_pthread_cond_broadcast = (int (*)()) dlsym(RTLD_NEXT, "pthread_cond_broadcast"); if (orig_pthread_cond_broadcast == NULL) { printf("pthread_cond_broadcast not found!!!\n"); exit(1); } } __atsortingbute__((__visibility__("default"))) int pthread_cond_broadcast(pthread_cond_t *cond) { return orig_pthread_cond_broadcast(cond); } 

Le programme pthread simple:

 #include  #include  #include  pthread_mutex_t cond_mutex; pthread_cond_t cond_var; int condition; void *thread0_work(void *arg) { pthread_mutex_lock(&cond_mutex); printf("Signal\n"); condition = 1; pthread_cond_broadcast(&cond_var); pthread_mutex_unlock(&cond_mutex); return NULL; } void *thread1_work(void *arg) { pthread_mutex_lock(&cond_mutex); while (condition == 0) { printf("Wait\n"); pthread_cond_wait(&cond_var, &cond_mutex); printf("Done waiting\n"); } pthread_mutex_unlock(&cond_mutex); return NULL; } int main() { pthread_t thread1; pthread_mutex_init(&cond_mutex, NULL); pthread_cond_init(&cond_var, NULL); pthread_create(&thread1, NULL, thread1_work, NULL); // Slowdown this thread, so the thread 1 does pthread_cond_wait. usleep(1000); thread0_work(NULL); pthread_join(thread1, NULL); return 0; } 

MODIFIER:

Pour glibc 2.11.1, gdb bt donne:

 (gdb) set environment LD_PRELOAD=./libintercept.so (gdb) run Starting program: /home/seguljac/intercept/main [Thread debugging using libthread_db enabled] [New Thread 0x7ffff7436700 (LWP 19165)] Wait Signal Before pthread_cond_broadcast Program received signal SIGSEGV, Segmentation fault. 0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0 (gdb) bt #0 0x00007ffff79ca0e7 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib/libpthread.so.0 #1 0x00007ffff7bdb769 in pthread_cond_broadcast () from ./libintercept.so #2 0x00000000004008e8 in thread0_work () #3 0x00000000004009a4 in main () 

EDIT 2:

(Résolu) Comme suggéré par R .. (merci!), Le problème est que sur ma plate-forme, pthread_cond_broadcast est un symbole versionné, et dlsym donne la mauvaise version. Ce blog explique cette situation en détail: http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/

L’appel via votre fonction semble aboutir à une version différente de la fonction:

 With LD_PRELOAD: __pthread_cond_broadcast_2_0 (cond=0x804a060) at old_pthread_cond_broadcast.c:37 Without LD_PRELOAD: pthread_cond_broadcast@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_broadcast.S:39 

Votre situation ressemble donc à cette question, c’est-à-dire que vous obtenez des versions incompatibles des fonctions de pthread: versioning de symboles et dlsym

Cette page donne un moyen de résoudre le problème, bien qu’un peu complexe: http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/