From: Bruno Haible Date: Fri, 16 May 2025 13:51:13 +0000 (+0200) Subject: sigprocmask: Make multithread-safe on native Windows. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9d8c4f480caf32ef072d85d26af68bc9a68d2fb;p=thirdparty%2Fgnulib.git sigprocmask: Make multithread-safe on native Windows. * lib/sigprocmask.c: Include glthread/lock.h. (sig_lock): New variable. (blocked_set): Remove 'volatile'. (sigprocmask, _gl_raise_SIGPIPE): Use the sig_lock. * modules/sigprocmask (Depends-on): Add lock. * doc/posix-functions/sigprocmask.texi: Mention the async-safety issue. --- diff --git a/ChangeLog b/ChangeLog index 95323c3a19..25cced87c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-05-16 Bruno Haible + + sigprocmask: Make multithread-safe on native Windows. + * lib/sigprocmask.c: Include glthread/lock.h. + (sig_lock): New variable. + (blocked_set): Remove 'volatile'. + (sigprocmask, _gl_raise_SIGPIPE): Use the sig_lock. + * modules/sigprocmask (Depends-on): Add lock. + * doc/posix-functions/sigprocmask.texi: Mention the async-safety issue. + 2025-05-16 Bruno Haible pthread-rwlock tests: Add a comment. diff --git a/doc/posix-functions/sigprocmask.texi b/doc/posix-functions/sigprocmask.texi index 7683986b3f..02bc537614 100644 --- a/doc/posix-functions/sigprocmask.texi +++ b/doc/posix-functions/sigprocmask.texi @@ -28,3 +28,9 @@ multi-threaded programs, in practice it is essentially equivalent to return convention. It's simpler to use @code{sigprocmask}, since it does not require linking with @code{-lpthread} on some platforms: glibc, NetBSD, OpenBSD, AIX. + +Note: While on POSIX platforms, @code{sigprocmask} is multithread-safe +and async-signal safe (cf. POSIX section ``Signal Actions'' +@url{https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03}), +the gnulib replacement on native Windows is only multithread-safe, +not async-signal safe. diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c index f79386c8d0..d52e191c44 100644 --- a/lib/sigprocmask.c +++ b/lib/sigprocmask.c @@ -24,6 +24,8 @@ #include #include +#include "glthread/lock.h" + #if HAVE_MSVC_INVALID_PARAMETER_HANDLER # include "msvc-inval.h" #endif @@ -84,6 +86,10 @@ signal_nothrow (int sig, handler_t handler) # define signal signal_nothrow #endif +/* This lock protects the variables defined in this file from concurrent + modification in multiple threads. */ +gl_lock_define_initialized(static, sig_lock) + /* Handling of gnulib defined signals. */ #if GNULIB_defined_SIGPIPE @@ -182,7 +188,7 @@ sigfillset (sigset_t *set) } /* Set of currently blocked signals. */ -static volatile sigset_t blocked_set /* = 0 */; +static sigset_t blocked_set /* = 0 */; /* Set of currently blocked and pending signals. */ static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; @@ -221,6 +227,8 @@ static volatile handler_t old_handlers[NSIG]; int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) { + gl_lock_lock (sig_lock); + if (old_set != NULL) *old_set = blocked_set; @@ -242,6 +250,7 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) new_blocked_set = blocked_set & ~*set; break; default: + gl_lock_unlock (sig_lock); errno = EINVAL; return -1; } @@ -286,6 +295,8 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) raise (sig); } } + + gl_lock_unlock (sig_lock); return 0; } @@ -334,11 +345,16 @@ rpl_signal (int sig, handler_t handler) int _gl_raise_SIGPIPE (void) { + gl_lock_lock (sig_lock); if (blocked_set & (1U << SIGPIPE)) - pending_array[SIGPIPE] = 1; + { + pending_array[SIGPIPE] = 1; + gl_lock_unlock (sig_lock); + } else { handler_t handler = SIGPIPE_handler; + gl_lock_unlock (sig_lock); if (handler == SIG_DFL) exit (128 + SIGPIPE); else if (handler != SIG_IGN) diff --git a/modules/sigprocmask b/modules/sigprocmask index 7f2e083803..79e7c7302f 100644 --- a/modules/sigprocmask +++ b/modules/sigprocmask @@ -8,6 +8,7 @@ m4/signalblocking.m4 Depends-on: signal-h stdint-h [test $HAVE_POSIX_SIGNALBLOCKING = 0] +lock [test $HAVE_POSIX_SIGNALBLOCKING = 0] raise [test $HAVE_POSIX_SIGNALBLOCKING = 0] msvc-inval [test $HAVE_POSIX_SIGNALBLOCKING = 0]