+2025-05-16 Bruno Haible <bruno@clisp.org>
+
+ 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 <bruno@clisp.org>
pthread-rwlock tests: Add a comment.
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.
#include <stdint.h>
#include <stdlib.h>
+#include "glthread/lock.h"
+
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
# include "msvc-inval.h"
#endif
# 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
}
/* 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 } */;
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;
new_blocked_set = blocked_set & ~*set;
break;
default:
+ gl_lock_unlock (sig_lock);
errno = EINVAL;
return -1;
}
raise (sig);
}
}
+
+ gl_lock_unlock (sig_lock);
return 0;
}
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)