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