Hi Here's another iteration of the patch. __libc_getspecific now considers the case were pthread is not loaded except when the containing file is being compiled for the loader.
The test case, when built without pthread, now works approprietly: diego@hird:~/src/test-cases/dlopen-error$ ./main.nopthread 0x1271b30 shobj: (nil) dlerror: ./non-existent.so: cannot open shared object file: No such file or directory errno1: [40000002] No such file or directory errno2: [40000002] No such file or directory However, when linked with it, dlerror still modifies the errno variable: diego@hird:~/src/test-cases/dlopen-error$ ./main.pthread 0x128d688 shobj: (nil) dlerror: ./non-existent.so: cannot open shared object file: No such file or directory errno1: [40000002] No such file or directory errno2: [4000004e] Function not implemented And breaking with gdb in cthread_getspecific I can confirm the implementation provided by pthread is not being called: diego@hird:~/src/test-cases/dlopen-error$ gdb ./main.pthread GNU gdb (Debian 7.10-1+b1) 7.10 ... Reading symbols from ./main.pthread...done. (gdb) break cthread_getspecific Function "cthread_getspecific" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (cthread_getspecific) pending. (gdb) run Starting program: /home/diego/src/test-cases/dlopen-error/main.pthread 0x128d688 [New Thread 17594.5] Breakpoint 1, cthread_getspecific (key=-1, pval=0x2003c9c) at ../sysdeps/mach/hurd/cthreads.c:42 42 *pval = NULL; (gdb) bt #0 cthread_getspecific (key=-1, pval=0x2003c9c) at ../sysdeps/mach/hurd/cthreads.c:42 #1 0x0109068a in __libc_getspecific (key=-1) at ../sysdeps/mach/hurd/cthreads.c:69 #2 0x01034218 in __dlerror () at dlerror.c:74 #3 0x080486ae in main (argc=1, argv=0x2003d84) at main.c:17 (gdb) I'm not sure what's going on. I've made some simple tests trying to imitate the setup but weak symbols were correctly overriden. Regards, Diego
Default values for thread-specific key handling functions. * sysdeps/mach/bits/libc-lock.h (__libc_ctf_call): New macro. (__libc_key_create, __libc_setspecific): Use macro above. * sysdeps/mach/hurd/bits/libc-lock.h: (__libc_ctf_call): New macro. (__libc_key_create, __libc_setspecific): Use macro above. * sysdeps/mach/hurd/cthreads.c (__libc_getspecific): Call cthread_getspecific only if pthread is present. --- sysdeps/mach/bits/libc-lock.h | 11 +++++++++-- sysdeps/mach/hurd/bits/libc-lock.h | 11 +++++++++-- sysdeps/mach/hurd/cthreads.c | 8 +++++--- 3 files changed, 23 insertions(+), 7 deletions(-) Index: glibc-2.21/sysdeps/mach/bits/libc-lock.h =================================================================== --- glibc-2.21.orig/sysdeps/mach/bits/libc-lock.h +++ glibc-2.21/sysdeps/mach/bits/libc-lock.h @@ -124,8 +124,15 @@ struct __libc_once #define __libc_mutex_unlock __mutex_unlock #endif -#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY) -#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL) +#define __libc_ctf_call(FUNC, ARGS, ELSE) \ + (&_cthread_init_routine && _cthread_init_routine \ + ? FUNC ARGS : ELSE) + +extern void *(*_cthread_init_routine) (void) __attribute__ ((weak)); +#define __libc_key_create(KEY,DEST) \ + __libc_ctf_call (cthread_keycreate, (KEY), 1) +#define __libc_setspecific(KEY,VAL) \ + __libc_ctf_call (cthread_setspecific, (KEY, VAL), 0) void *__libc_getspecific (__libc_key_t key); /* XXX until cthreads supports recursive locks */ Index: glibc-2.21/sysdeps/mach/hurd/bits/libc-lock.h =================================================================== --- glibc-2.21.orig/sysdeps/mach/hurd/bits/libc-lock.h +++ glibc-2.21/sysdeps/mach/hurd/bits/libc-lock.h @@ -197,8 +197,15 @@ struct __libc_once /* Type for key of thread specific data. */ typedef cthread_key_t __libc_key_t; -#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY) -#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL) +#define __libc_ctf_call(FUNC, ARGS, ELSE) \ + (&_cthread_init_routine && _cthread_init_routine \ + ? FUNC ARGS : ELSE) + +extern void *(*_cthread_init_routine) (void) __attribute__ ((weak)); +#define __libc_key_create(KEY,DEST) \ + __libc_ctf_call (cthread_keycreate, (KEY), 1) +#define __libc_setspecific(KEY,VAL) \ + __libc_ctf_call (cthread_setspecific, (KEY, VAL), 0) void *__libc_getspecific (__libc_key_t key); #endif /* _CTHREADS_ */ Index: glibc-2.21/sysdeps/mach/hurd/cthreads.c =================================================================== --- glibc-2.21.orig/sysdeps/mach/hurd/cthreads.c +++ glibc-2.21/sysdeps/mach/hurd/cthreads.c @@ -54,12 +54,16 @@ cthread_setspecific (key, val) } /* Call cthread_getspecific which gets a pointer to the return value instead - of just returning it. */ + of just returning it. + Follow NPTL, return NULL when pthread is not loaded. */ void * __libc_getspecific (key) cthread_key_t key; { - void *val; - cthread_getspecific (key, &val); + void *val = NULL; +#if !IS_IN(rtld) + if (&_cthread_init_routine && _cthread_init_routine) + cthread_getspecific (key, &val); +#endif return val; }