Blame SOURCES/0001-BUILD-threads-workaround-for-late-loading-of-libgcc_s.patch

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