99 lines
3.1 KiB
Diff
99 lines
3.1 KiB
Diff
From 10c627ab2ebeb0a38ae8df477a5f2d870ad77f7c Mon Sep 17 00:00:00 2001
|
|
From: Willy Tarreau <w@1wt.eu>
|
|
Date: Wed, 9 Sep 2020 17:07:54 +0200
|
|
Subject: [PATCH 1/2] BUILD: threads: better workaround for late loading of
|
|
libgcc_s
|
|
|
|
Commit 77b98220e ("BUG/MINOR: threads: work around a libgcc_s issue with
|
|
chrooting") tried to address an issue with libgcc_s being loaded too late.
|
|
But it turns out that the symbol used there isn't present on armhf, thus
|
|
it breaks the build.
|
|
|
|
Given that the issue manifests itself during pthread_exit(), the safest
|
|
and most portable way to test this is to call pthread_exit(). For this
|
|
we create a dummy thread which exits, during the early boot. This results
|
|
in the relevant library to be loaded if needed, making sure that a later
|
|
call to pthread_exit() will still work. It was tested to work fine under
|
|
linux on the following platforms:
|
|
|
|
glibc:
|
|
- armhf
|
|
- aarch64
|
|
- x86_64
|
|
- sparc64
|
|
- ppc64le
|
|
|
|
musl:
|
|
- mipsel
|
|
|
|
Just running the code under strace easily shows the call in the dummy
|
|
thread, for example here on armhf:
|
|
|
|
$ strace -fe trace=file ./haproxy -v 2>&1 | grep gcc_s
|
|
[pid 23055] open("/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
|
|
|
|
The code was isolated so that it's easy to #ifdef it out if needed.
|
|
This should be backported where the patch above is backported (likely
|
|
2.0).
|
|
|
|
(cherry picked from commit f734ebfac4c406f245347527bd0e5831a251cc61)
|
|
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
|
---
|
|
src/thread.c | 33 ++++++++++++++++++++++-----------
|
|
1 file changed, 22 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/src/thread.c b/src/thread.c
|
|
index 5eb68e33a..eeb0e04f4 100644
|
|
--- a/src/thread.c
|
|
+++ b/src/thread.c
|
|
@@ -189,6 +189,27 @@ static int thread_cpus_enabled()
|
|
return ret;
|
|
}
|
|
|
|
+/* Depending on the platform and how libpthread was built, pthread_exit() may
|
|
+ * involve some code in libgcc_s that would be loaded on exit for the first
|
|
+ * time, causing aborts if the process is chrooted. It's harmless bit very
|
|
+ * dirty. There isn't much we can do to make sure libgcc_s is loaded only if
|
|
+ * needed, so what we do here is that during early boot we create a dummy
|
|
+ * thread that immediately exits. This will lead to libgcc_s being loaded
|
|
+ * during boot on the platforms where it's required.
|
|
+ */
|
|
+static void *dummy_thread_function(void *data)
|
|
+{
|
|
+ pthread_exit(NULL);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static inline void preload_libgcc_s(void)
|
|
+{
|
|
+ pthread_t dummy_thread;
|
|
+ pthread_create(&dummy_thread, NULL, dummy_thread_function, NULL);
|
|
+ pthread_join(dummy_thread, NULL);
|
|
+}
|
|
+
|
|
__attribute__((constructor))
|
|
static void __thread_init(void)
|
|
{
|
|
@@ -201,17 +222,7 @@ static void __thread_init(void)
|
|
exit(1);
|
|
}
|
|
|
|
-#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(__GNU_LIBRARY__) && !defined(__clang__)
|
|
- /* make sure libgcc_s is already loaded, because pthread_exit() may
|
|
- * may need it on exit after the chroot! _Unwind_Find_FDE() is defined
|
|
- * there since gcc 3.0, has no side effect, doesn't take any argument
|
|
- * and seems to be present on all supported platforms.
|
|
- */
|
|
- {
|
|
- extern void _Unwind_Find_FDE(void);
|
|
- _Unwind_Find_FDE();
|
|
- }
|
|
-#endif
|
|
+ preload_libgcc_s();
|
|
|
|
thread_cpus_enabled_at_boot = thread_cpus_enabled();
|
|
|
|
--
|
|
2.26.2
|
|
|