]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[bug2332] Create & cancel a dummy thread to warm-up the pthread runtime
authorJuergen Perlinger <perlinger@ntp.org>
Sat, 26 Sep 2015 13:17:13 +0000 (13:17 +0000)
committerJuergen Perlinger <perlinger@ntp.org>
Sat, 26 Sep 2015 13:17:13 +0000 (13:17 +0000)
 instead of linking against libgcc_s on Linux targets

bk: 56069ad9LJL0_2IfUi_PipCyi6giZQ

ChangeLog
ntpd/ntpd.c
sntp/m4/ntp_libntp.m4

index 266244bf2fd850831895852799484ab0e97c5865..d8da657827f1f36d0706c11b6d84d2fe599b8e90 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
 ---
+* [Bug2332](reopened) Exercise thread cancellation once before dropping
+  privileges and limiting resources in NTPD removes the need to link
+  forcefully against 'libgcc_s' which does not always work. J.Perlinger
 * [Bug 2595] ntpdate man page quirks.  Hal Murray, Harlan Stenn.
 * [Bug 2625] Deprecate flag1 in local refclock.  Hal Murray, Harlan Stenn.
 * [Bug 2817] Stop locking ntpd into memory by default under Linux.  H.Stenn.
index a14d02c503d90e1c40d2c4c7b9631544e97f4474..a517391ba522f0574679626e708ca4a79f7a77b8 100644 (file)
 #include "ntp_libopts.h"
 #include "ntpd-opts.h"
 
+/* there's a short treatise below what the thread stuff is for */
+#if defined(HAVE_PTHREADS) && HAVE_PTHREADS && !defined(NO_THREADS)
+# ifdef HAVE_PTHREAD_H
+#  include <pthread.h>
+# endif
+# define NEED_PTHREAD_WARMUP
+#endif
+
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -232,6 +240,68 @@ static void        library_unexpected_error(const char *, int,
 #endif /* !SIM */
 
 
+/* Bug2332 unearthed a problem in the interaction of reduced user
+ * privileges, the limits on memory usage and some versions of the
+ * pthread library on Linux systems. The 'pthread_cancel()' function and
+ * likely some others need to track the stack of the thread involved,
+ * and uses a function that comes from GCC (--> libgcc_s.so) to do
+ * this. Unfortunately the developers of glibc decided to load the
+ * library on demand, which speeds up program start but can cause
+ * trouble here: Due to all the things NTPD does to limit its resource
+ * usage, this deferred load of libgcc_s does not always work once the
+ * restrictions are in effect.
+ *
+ * One way out of this was attempting a forced link against libgcc_s
+ * when possible because it makes the library available immediately
+ * without deferred load. (The symbol resolution would still be dynamic
+ * and on demand, but the code would already be in the process image.)
+ *
+ * This is a tricky thing to do, since it's not necessary everywhere,
+ * not possible everywhere, has shown to break the build of other
+ * programs in the NTP suite and is now generally frowned upon.
+ *
+ * So we take a different approach here: We creat a worker thread that does
+ * actually nothing except waiting for cancellation and cancel it. If
+ * this is done before all the limitations are put in place, the
+ * machinery is pre-heated and all the runtime stuff should be in place
+ * and useable when needed.
+ *
+ * This uses only the standard pthread API and should work with all
+ * implementations of pthreads. It is not necessary everywhere, but it's
+ * cheap enough to go on nearly unnoticed.
+ */
+#ifdef NEED_PTHREAD_WARMUP
+
+/* simple thread function: sleep until cancelled, just to exercise
+ * thread cancellation.
+ */
+static void*
+my_pthread_warmup_worker(
+       void *thread_args)
+{
+       (void)thread_args;
+       for (;;)
+               sleep(10);
+       return NULL;
+}
+       
+/* pre-heat threading: create a thread and cancel it, just to exercise
+ * thread cancellation.
+ */
+static void
+my_pthread_warmup(void)
+{
+       pthread_t thread;
+       int       rc;
+       rc = pthread_create(
+               &thread, NULL, my_pthread_warmup_worker, NULL);
+       if (0 == rc) {
+               pthread_cancel(thread);
+               pthread_join(thread, NULL);
+       }
+}
+
+#endif /*defined(NEED_PTHREAD_WARMUP)*/
 
 
 void
@@ -445,6 +515,10 @@ ntpdmain(
        int             zero;
 # endif
 
+# ifdef NEED_PTHREAD_WARMUP
+       my_pthread_warmup();
+# endif
+       
 # ifdef HAVE_UMASK
        uv = umask(0);
        if (uv)
index 3999b6e947c4fa4d31ee1ca077127405ed28ba49..01d82fcd5504318f19bb45272e3a121b09ce52dc 100644 (file)
@@ -347,20 +347,6 @@ case "$enable_thread_support" in
         yes)
            PTHREAD_LIBS="$LTHREAD_LIBS"
            have_pthreads=yes
-           # Bug 2332: With GCC we need to force a reference to libgcc_s
-           # (if libgcc_s exists) or the combination of
-           # threads + setuid + mlockall does not work on linux because
-           # thread cancellation fails to load libgcc_s with dlopen().
-           # We have to pass this all as linker options to avoid argument
-           # reordering by libtool.
-           # HMS: The fix below seems to break a number of test programs,
-           # as it means pthread_once() can't be found.
-           case "$GCC$with_gnu_ld" in
-           Xyesyes)
-               AC_CHECK_LIB([gcc_s], [exit],
-                       [PTHREAD_LIBS="$LTHREAD_LIBS -Wl,--no-as-needed,-lgcc_s,--as-needed"])
-               ;;
-           esac
        esac
     esac
 esac