BUG/MINOR: threads: work around a libgcc_s issue with chrooting

Sander Hoentjen reported another issue related to libgcc_s in issue #671.
What happens is that when the old process quits, pthread_exit() calls
something from libgcc_s.so after the process was chrooted, and this is
the first call to that library, causing an attempt to load it. In a
chroot, this fails, thus libthread aborts. The behavior widely differs
between operating systems because some decided to use a static build for
this library.

In 2.2 this was resolved as a side effect of a workaround for the same issue
with the backtrace() call, which is also in libgcc_s. This was in commit
0214b45 ("MINOR: debug: call backtrace() once upon startup"). But backtraces
are not necessarily enabled, and we need something for older versions.

By inspecting a significant number of ligcc_s on various gcc versions and
platforms, it appears that a few functions have been present since gcc 3.0,
one of which, _Unwind_Find_FDE() has no side effect (it only returns a
pointer). What this patch does is that in the thread initialization code,
if built with gcc >= 3.0, a call to this function is made in order to make
sure that libgcc_s is loaded at start up time and that there will be no
need to load it upon exit.

An easy way to check which libs are loaded under Linux is :

  $ strace -e trace=openat ./haproxy -v

With this patch applied, libgcc_s now appears during init.

Sander confirmed that this patch was enough to put an end to the core
dumps on exit in 2.0, so this patch should be backported there, and maybe
as far as 1.8.
diff --git a/src/thread.c b/src/thread.c
index 3ec8d8c..b902aa3 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -201,6 +201,18 @@
 		exit(1);
 	}
 
+#if defined(__GNUC__) && (__GNUC__ >= 3) && !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
+
 	thread_cpus_enabled_at_boot = thread_cpus_enabled();
 
 	memprintf(&ptr, "Built with multi-threading support (MAX_THREADS=%d, default=%d).",