From: Juergen Perlinger Date: Sat, 26 Sep 2015 13:17:13 +0000 (+0000) Subject: [bug2332] Create & cancel a dummy thread to warm-up the pthread runtime X-Git-Tag: NTP_4_3_74~3^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0287a32656b83f8a67d9f9f691a893a6e43cfca0;p=thirdparty%2Fntp.git [bug2332] Create & cancel a dummy thread to warm-up the pthread runtime instead of linking against libgcc_s on Linux targets bk: 56069ad9LJL0_2IfUi_PipCyi6giZQ --- diff --git a/ChangeLog b/ChangeLog index 266244bf2..d8da65782 100644 --- 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. diff --git a/ntpd/ntpd.c b/ntpd/ntpd.c index a14d02c50..a517391ba 100644 --- a/ntpd/ntpd.c +++ b/ntpd/ntpd.c @@ -27,6 +27,14 @@ #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 +# endif +# define NEED_PTHREAD_WARMUP +#endif + #ifdef HAVE_UNISTD_H # include #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) diff --git a/sntp/m4/ntp_libntp.m4 b/sntp/m4/ntp_libntp.m4 index 3999b6e94..01d82fcd5 100644 --- a/sntp/m4/ntp_libntp.m4 +++ b/sntp/m4/ntp_libntp.m4 @@ -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