[uclibc-ng-devel] pthread_mutex_*() functions, dynamic vs. static linking
thomas.petazzoni at free-electrons.com
Thu Aug 11 23:33:27 CEST 2016
Today I was investigating a link issue that occurs in Buildroot with
the libarchive package. It turns out that the code of this package
uses pthread_mutex_lock/pthread_mutex_unlock in some places to be
thread-safe, but does *not* link with the libpthread library.
I was originally surprised that this could even work, but I discovered
that the libc intentionally provides a stub implementation of
pthread_mutex_lock/unlock. The idea behind this is that a library can
use pthread_mutex_lock/unlock without linking to libpthread. This way,
if the application using the library is single-threaded and doesn't
link with libpthread, pthread_mutex_lock/unlock are no-ops. On the
other hand, if the application using the library is multi-threaded, it
will link with libpthread, and therefore the libpthread versions of
pthread_mutex_lock/unlock will be used.
This all seems good, until you get to static linking. Indeed with
uClibc-ng, the following program:
will link perfectly fine with dynamic linking:
$ ./host/usr/bin/arm-linux-gcc -o foo foo.c
$ ./host/usr/bin/arm-linux-readelf -d foo | grep NEEDED
0x00000001 (NEEDED) Shared library: [libc.so.0]
but will fail to build with static linking:
$ ./host/usr/bin/arm-linux-gcc -o foo foo.c -static
/tmp/ccda8vkc.o: In function `main':
foo.c:(.text+0x14): undefined reference to `pthread_mutex_lock'
collect2: error: ld returned 1 exit status
And this explains the build failures like
that we are seeing in Buildroot.
It is worth mentioning that using the musl C library, this test case
works fine in both dynamic linking and static linking cases (and the
libarchive error also does not occur).
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
More information about the devel