[uclibc-ng-devel] pthread_mutex_*() functions, dynamic vs. static linking

Thomas Petazzoni 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:

#include <pthread.h>

int main(void)
	pthread_mutex_t lock;
	return 0;

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 mailing list