diff options
author | Viktor Dukhovni <ietf-dane@dukhovni.org> | 2021-04-20 13:56:01 -0400 |
---|---|---|
committer | Viktor Dukhovni <ietf-dane@dukhovni.org> | 2021-04-20 23:27:36 -0400 |
commit | 5b65d9fbe686d0cd8460a80a7c0d78e6520432e4 (patch) | |
tree | 12b40b688c24536e425c408f23cb4a21134fc649 | |
parent | 5344f8404a0ec0cec250bee1f92527950f492f29 (diff) | |
download | haskell-5b65d9fbe686d0cd8460a80a7c0d78e6520432e4.tar.gz |
Block signals in the ticker thread
This avoids surprises in the non-threaded runtime with blocked signals killing
the process because they're only blocked in the main thread and not in the
ticker thread.
Also backport improved compile-time detection of pthread_setname_np() and/or
-rw-r--r-- | configure.ac | 70 | ||||
-rw-r--r-- | rts/posix/OSThreads.c | 8 | ||||
-rw-r--r-- | rts/posix/itimer/Pthread.c | 37 |
3 files changed, 102 insertions, 13 deletions
diff --git a/configure.ac b/configure.ac index c680bf04b5..44586446dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1162,20 +1162,72 @@ AC_CHECK_FUNC(pthread_create, AC_DEFINE_UNQUOTED([NEED_PTHREAD_LIB], [$need_lpthread], [Define 1 if we need to link code using pthreads with -lpthread]) +dnl Setting thread names +dnl ~~~~~~~~~~~~~~~~~~~~ +dnl The portability situation here is complicated: +dnl +dnl * FreeBSD supports pthread_set_name_np in <pthread_np.h> +dnl and (if not _POSIX_SOURCE) pthread_setname_np() in <pthread.h> +dnl because of the conditional visibility, we prefer the former. +dnl * glibc supports pthread_setname_np +dnl * Darwin supports pthread_setname_np but does not take a +dnl pthread_t argument. +dnl +AC_CHECK_HEADERS([pthread_np.h]) + dnl ** pthread_setname_np is a recent addition to glibc, and OS X has dnl a different single-argument version. AC_CHECK_LIB(pthread, pthread_setname_np) -AC_MSG_CHECKING(for pthread_setname_np) -AC_LINK_IFELSE([AC_LANG_PROGRAM( -[[ -#define _GNU_SOURCE -#include <pthread.h> -]], -[[pthread_setname_np(pthread_self(), "name");]])], + +AC_MSG_CHECKING([for pthread_setname_np (Darwin)]) +AC_LINK_IFELSE([ + AC_LANG_PROGRAM( + [[ + #include <pthread.h> + ]], + [[pthread_setname_np("name");]] + )], + [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_DARWIN], [1], + [Define to 1 if you have the Darwin version of pthread_setname_np]) + ], + AC_MSG_RESULT(no) +) + +dnl glibc +AC_MSG_CHECKING([for pthread_setname_np (glibc)]) +AC_LINK_IFELSE([ + AC_LANG_PROGRAM( + [[ + #define _GNU_SOURCE + #include <pthread.h> + ]], + [[pthread_setname_np(pthread_self(), "name");]] + )], + [ AC_MSG_RESULT(yes) AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], [1], - [Define to 1 if you have the glibc version of pthread_setname_np]), - AC_MSG_RESULT(no) + [Define to 1 if you have the glibc version of pthread_setname_np]) + ], + AC_MSG_RESULT(no) +) + +dnl FreeBSD +AC_MSG_CHECKING([for pthread_set_name_np]) +AC_LINK_IFELSE([ + AC_LANG_PROGRAM( + [[ + #include <pthread_np.h> + ]], + [[pthread_set_name_np(pthread_self(), "name");]] + )], + [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_PTHREAD_SET_NAME_NP], [1], + [Define to 1 if you have pthread_set_name_np]) + ], + AC_MSG_RESULT(no) ) dnl ** check for eventfd which is needed by the I/O manager diff --git a/rts/posix/OSThreads.c b/rts/posix/OSThreads.c index 6c09f86c7f..481b0f8c17 100644 --- a/rts/posix/OSThreads.c +++ b/rts/posix/OSThreads.c @@ -30,7 +30,7 @@ #if defined(HAVE_PTHREAD_H) #include <pthread.h> -#if defined(freebsd_HOST_OS) +#if defined(HAVE_PTHREAD_NP_H) #include <pthread_np.h> #endif #endif @@ -137,8 +137,12 @@ createOSThread (OSThreadId* pId, char *name STG_UNUSED, int result = pthread_create(pId, NULL, startProc, param); if (!result) { pthread_detach(*pId); -#if defined(HAVE_PTHREAD_SETNAME_NP) +#if defined(HAVE_PTHREAD_SET_NAME_NP) + pthread_set_name_np(*pId, name); +#elif defined(HAVE_PTHREAD_SETNAME_NP) pthread_setname_np(*pId, name); +#elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) + pthread_setname_np(name); #endif } return result; diff --git a/rts/posix/itimer/Pthread.c b/rts/posix/itimer/Pthread.c index 6f86337ff5..73b1eba5de 100644 --- a/rts/posix/itimer/Pthread.c +++ b/rts/posix/itimer/Pthread.c @@ -62,6 +62,9 @@ #include <string.h> #include <pthread.h> +#if defined(HAVE_PTHREAD_NP_H) +#include <pthread_np.h> +#endif #include <unistd.h> #include <fcntl.h> @@ -167,6 +170,11 @@ initTicker (Time interval, TickProc handle_tick) itimer_interval = interval; stopped = false; exited = false; +#if defined(HAVE_SIGNAL_H) + sigset_t mask, omask; + int sigret; +#endif + int ret; initCondition(&start_cond); initMutex(&mutex); @@ -174,10 +182,35 @@ initTicker (Time interval, TickProc handle_tick) /* * We can't use the RTS's createOSThread here as we need to remain attached * to the thread we create so we can later join to it if requested + * + * On FreeBSD 12.2 pthread_set_name_np() is unconditionally declared in + * <pthread_np.h>, while pthread_setname_np() is conditionally declared in + * <pthread.h> when _POSIX_SOURCE is not defined, but we're including + * <PosixSource.h>, so must use pthread_set_name_np() instead. See similar + * code in "rts/posix/OSThreads.c". + * + * Create the thread with all blockable signals blocked, leaving signal + * handling to the main and/or other threads. This is especially useful in + * the non-threaded runtime, where applications might expect sigprocmask(2) + * to effectively block signals. */ - if (! pthread_create(&thread, NULL, itimer_thread_func, (void*)handle_tick)) { -#if defined(HAVE_PTHREAD_SETNAME_NP) +#if defined(HAVE_SIGNAL_H) + sigfillset(&mask); + sigret = pthread_sigmask(SIG_SETMASK, &mask, &omask); +#endif + ret = pthread_create(&thread, NULL, itimer_thread_func, (void*)handle_tick); +#if defined(HAVE_SIGNAL_H) + if (sigret == 0) + pthread_sigmask(SIG_SETMASK, &omask, NULL); +#endif + + if (ret == 0) { +#if defined(HAVE_PTHREAD_SET_NAME_NP) + pthread_set_name_np(thread, "ghc_ticker"); +#elif defined(HAVE_PTHREAD_SETNAME_NP) pthread_setname_np(thread, "ghc_ticker"); +#elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) + pthread_setname_np("ghc_ticker"); #endif } else { barf("Itimer: Failed to spawn thread: %s", strerror(errno)); |