H Thomas,
Thomas Petazzoni wrote,
Hello,
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;
pthread_mutex_lock(&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
http://autobuild.buildroot.net/results/01b/01b7088a06e7310c8773e78e8be4f6e8…
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).
What about following patch, which creates dummies for
pthread_mutex_* functions in the !SHARED case:
From 8d11aa1b9a983e0422dffa84eb1a7b71c616a096 Mon Sep
17 00:00:00 2001
From: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
Date: Thu, 18 Aug 2016 08:17:36 +0200
Subject: [PATCH] add dummies
Signed-off-by: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
---
libc/misc/internals/__uClibc_main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
index 9bb81fc..9320039 100644
--- a/libc/misc/internals/__uClibc_main.c
+++ b/libc/misc/internals/__uClibc_main.c
@@ -81,6 +81,9 @@ static int __pthread_return_0 (pthread_mutex_t *unused) { return 0; }
weak_alias (__pthread_return_0, __pthread_mutex_lock)
weak_alias (__pthread_return_0, __pthread_mutex_trylock)
weak_alias (__pthread_return_0, __pthread_mutex_unlock)
+weak_alias (__pthread_return_0, pthread_mutex_lock)
+weak_alias (__pthread_return_0, pthread_mutex_trylock)
+weak_alias (__pthread_return_0, pthread_mutex_unlock)
int weak_function
__pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
--
1.7.10.4
/usr/bin/arm-openadk-linux-uclibceabihf-gcc -o foo foo.c -static
$ file foo
foo: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, not stripped
$ nm foo|grep pthread_mutex
00010478 W __pthread_mutex_init
00010470 W __pthread_mutex_lock
00010470 W __pthread_mutex_trylock
00010470 W __pthread_mutex_unlock
00010470 W pthread_mutex_lock
00010470 W pthread_mutex_trylock
00010470 W pthread_mutex_unlock
best regards
Waldemar