Re: weak symbols
Martijn van Duren wrote: > Could you inform me on the preferred way for making a library thread safe? > - always linking in lpthread into the library (which causes some extra > bloat in the loading of the extra library). > - making the required symbols available via weak symbols, as per my > original question. (which might not be very portable and might make the > code less transparent) > - making custom functions which load in the required symbols via dlsym > (which requires extra LoC) > - another method I haven't thought of? The second option is probably the best approach today. There are some annoying downsides to linking directly against libpthread, since it then requires every application to do the same. Using dlsym doesn't seem much much better than using weak symbols.
Re: weak symbols
On 04/08/15 08:10, Philip Guenther wrote: On Tue, 7 Apr 2015, Martijn van Duren wrote: I'm currently experimenting with weak symbols for a library that I want to be thread safe without hard linking in the entire libpthread. To test this I've set up the following code: ... When compiling with pthread it seems it only resolves pthread_mutex_init, but still uses the weak pthread_create and executes secondary lock first: ... Could someone please elaborate on what I'm doing wrong and how to implement these weak symbols properly. Thank you in advance. If the symbol is defined in the base executable, then it cannot be overriden by a shared library, regardless of its binding (global or weak) in the executable. Indeed, the reference will be resolved when the executable is created, leaving no relocation dependent on the symbol definition. If you want to work with symbol interposition like this, you'll need to actually build shared libraries. Philip Guenther Thank you, this seems to work. I've also been looking at other ways to make this work, like by making a custom cpthread_* function, which in turns loads pthread_create via dlsym(RTLD_NEXT, "pthread_create") and test the output for NULL, which also seems to work. Could you inform me on the preferred way for making a library thread safe? - always linking in lpthread into the library (which causes some extra bloat in the loading of the extra library). - making the required symbols available via weak symbols, as per my original question. (which might not be very portable and might make the code less transparent) - making custom functions which load in the required symbols via dlsym (which requires extra LoC) - another method I haven't thought of? To make my question even more concrete: I intend to lock a file with flock, which isn't thread safe. Is there a (portable) way to lock a file for both processes and threads alike, or should I construct a wrapper with extra locking as per my question mentioned above? Martijn van Duren
Re: weak symbols
On Tue, 7 Apr 2015, Martijn van Duren wrote: > I'm currently experimenting with weak symbols for a library that I want > to be thread safe without hard linking in the entire libpthread. > > To test this I've set up the following code: ... > When compiling with pthread it seems it only resolves > pthread_mutex_init, but still uses the weak pthread_create and executes > secondary lock first: ... > Could someone please elaborate on what I'm doing wrong and how to implement > these weak symbols properly. Thank you in advance. If the symbol is defined in the base executable, then it cannot be overriden by a shared library, regardless of its binding (global or weak) in the executable. Indeed, the reference will be resolved when the executable is created, leaving no relocation dependent on the symbol definition. If you want to work with symbol interposition like this, you'll need to actually build shared libraries. Philip Guenther
weak symbols
Hello misc@, I'm currently experimenting with weak symbols for a library that I want to be thread safe without hard linking in the entire libpthread. To test this I've set up the following code: #include #include #include #include #include pthread_mutex_t mut; #pragma weak pthread_create #pragma weak pthread_mutex_init #pragma weak pthread_mutex_lock #pragma weak pthread_mutex_unlock int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { start_routine(arg); return 0; } int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { return 0; } int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; } int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; } void * thread(void *arg) { sleep(1); pthread_mutex_lock(&mut); printf("Got secondary lock\n"); sleep(2); pthread_mutex_unlock(&mut); printf("Released secondary lock\n"); return NULL; } int main() { pthread_t tid; pthread_mutex_init(&mut, NULL); pthread_create(&tid, NULL, &thread, NULL); pthread_mutex_lock(&mut); printf("Got main lock\n"); sleep(2); pthread_mutex_unlock(&mut); printf("Released main lock\n"); sleep(2); } When compiling without pthread it runs as expected: $ gcc ./test.c $ ./a.out Got secondary lock Released secondary lock Got main lock Released main lock $ nm -e ./a.out 002011f0 a _DYNAMIC 00301338 a _GLOBAL_OFFSET_TABLE_ W _Jv_RegisterClasses 004013d8 A __bss_start W __cxa_atexit -> _dl_searchnum 00201018 D __dso_handle 0f30 T __fini 00301338 D __got_start 00201008 D __guard_local 0ad0 T __init W __init_tcb 00201010 D __progname 00401440 B __progname_storage 0c90 W __register_frame_info -> (null) U __stack_smash_handler 0b60 T __start 00401420 B _dl_skipnum 004013d8 A _edata 00401548 A _end 0b60 T _start 00401428 B environ 0e85 T main 00401540 B mut 0dd4 W pthread_create -> __got_end 0dfd W pthread_mutex_init -> __data_start 0e10 W pthread_mutex_lock -> exit 0e1f W pthread_mutex_unlock -> atexit U puts U sleep F test.c 0e2e T thread When compiling with pthread it seems it only resolves pthread_mutex_init, but still uses the weak pthread_create and executes secondary lock first: $ gcc -lpthread ./test.c $ ./a.out Got secondary lock Released secondary lock Got main lock Released main lock $ nm -e ./a.out 002012b0 a _DYNAMIC 00301408 a _GLOBAL_OFFSET_TABLE_ W _Jv_RegisterClasses 004014a8 A __bss_start W __cxa_atexit -> _dl_searchnum 002010d8 D __dso_handle 0ff0 T __fini 00301408 D __got_start 002010c8 D __guard_local 0b90 T __init W __init_tcb -> pthread_mutex_init 002010d0 D __progname 00401520 B __progname_storage 0d50 W __register_frame_info -> (null) U __stack_smash_handler 0c20 T __start 00401500 B _dl_skipnum 004014a8 A _edata 00401628 A _end 0c20 T _start 00401508 B environ 0f45 T main 00401620 B mut 0e94 W pthread_create -> __got_end 0ed0 W pthread_mutex_lock -> exit 0edf W pthread_mutex_unlock -> atexit U puts U sleep F test.c 00000eee T thread Could someone please elaborate on what I'm doing wrong and how to implement these weak symbols properly. Thank you in advance. Sincerely, Martijn van Duren