Paul Eggert wrote:
> For years, POSIX has recommended that multithreaded apps use 
> pthread_sigmask instead of sigprocmask.

The module 'asyncsafe-spin' is also easy to handle, because the comment
in lib/asyncsafe-spin.h indicates that the code was meant to use
pthread_sigmask, and sigprocmask was actually used only to avoid a link
requirement.


2026-04-04  Bruno Haible  <[email protected]>

        asyncsafe-spin: Prefer pthread_sigmask over sigprocmask.
        Suggested by Paul Eggert.
        * lib/asyncsafe-spin.c (asyncsafe_spin_lock, asyncsafe_spin_unlock): Use
        pthread_sigmask instead of sigprocmask.
        * modules/asyncsafe-spin (Depends-on): Add pthread_sigmask. Remove
        sigprocmask.
        (Link): New section.
        * modules/asyncsafe-spin-tests (Makefile.am): Link test-asyncsafe-spin1
        with $(PTHREAD_SIGMASK_LIB).
        * modules/jit/cache-tests (Makefile.am): Link test-cache with
        $(PTHREAD_SIGMASK_LIB).

diff --git a/lib/asyncsafe-spin.c b/lib/asyncsafe-spin.c
index 8400ad87a3..1c2c5950a7 100644
--- a/lib/asyncsafe-spin.c
+++ b/lib/asyncsafe-spin.c
@@ -42,22 +42,19 @@ asyncsafe_spin_lock (asyncsafe_spinlock_t *lock,
      On platforms other than native Windows, it is useful to do the same
      thing also within a signal handler, since signals may remain enabled
      while a signal handler runs.  It is possible to do this because
-     sigprocmask() is safe to call from within a signal handler, see
+     pthread_sigmask() is safe to call from within a signal handler, see
      POSIX section "Signal Actions"
      
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03>.
-     (In other words, sigprocmask() is atomic, because it is implemented as a
+     (In other words, pthread_sigmask() is atomic, because it is implemented 
as a
      system call.)
-     Whereas on native Windows, sigprocmask() is not atomic, because it
-     manipulates global variables.  Therefore in this case, we are *not*
-     allowed to call it from within a signal handler.  */
+     Whereas on native Windows, pthread_sigmask() = sigprocmask() is not 
atomic,
+     because it manipulates global variables.  Therefore in this case, we are
+     *not* allowed to call it from within a signal handler.  */
 
-  /* FIXME: Use pthread_sigmask, not sigprocmask, as the two functions
-     behave differently on macOS and the sigprocmask behavior can cause
-     this thread to race with other threads in harmful ways.  */
 #if defined _WIN32 && !defined __CYGWIN__
   if (!from_signal_handler)
 #endif
-    sigprocmask (SIG_BLOCK, mask, saved_mask);
+    pthread_sigmask (SIG_BLOCK, mask, saved_mask);
 
   glthread_spinlock_lock (lock);
 }
@@ -70,13 +67,10 @@ asyncsafe_spin_unlock (asyncsafe_spinlock_t *lock,
   if (glthread_spinlock_unlock (lock))
     abort ();
 
-  /* FIXME: Use pthread_sigmask, not sigprocmask, as the two functions
-     behave differently on macOS and the sigprocmask behavior can cause
-     this thread to race with other threads in harmful ways.  */
 #if defined _WIN32 && !defined __CYGWIN__
   if (!from_signal_handler)
 #endif
-    sigprocmask (SIG_SETMASK, saved_mask, NULL);
+    pthread_sigmask (SIG_SETMASK, saved_mask, NULL);
 }
 
 void
diff --git a/modules/asyncsafe-spin b/modules/asyncsafe-spin
index 9c3d0097f1..c90cf2a336 100644
--- a/modules/asyncsafe-spin
+++ b/modules/asyncsafe-spin
@@ -7,8 +7,8 @@ lib/asyncsafe-spin.c
 
 Depends-on:
 signal-h
+pthread_sigmask
 bool
-sigprocmask
 spin
 
 configure.ac:
@@ -19,6 +19,9 @@ lib_SOURCES += asyncsafe-spin.c
 Include:
 "asyncsafe-spin.h"
 
+Link:
+$(PTHREAD_SIGMASK_LIB)
+
 License:
 LGPLv2+
 
diff --git a/modules/asyncsafe-spin-tests b/modules/asyncsafe-spin-tests
index dacb26aaac..c39d11438d 100644
--- a/modules/asyncsafe-spin-tests
+++ b/modules/asyncsafe-spin-tests
@@ -18,4 +18,5 @@ AC_REQUIRE([gl_SEMAPHORE])
 Makefile.am:
 TESTS += test-asyncsafe-spin1 test-asyncsafe-spin2
 check_PROGRAMS += test-asyncsafe-spin1 test-asyncsafe-spin2
+test_asyncsafe_spin1_LDADD = $(LDADD) @PTHREAD_SIGMASK_LIB@
 test_asyncsafe_spin2_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ 
@LIB_SEMAPHORE@
diff --git a/modules/jit/cache-tests b/modules/jit/cache-tests
index 36fe90b8e9..360d184723 100644
--- a/modules/jit/cache-tests
+++ b/modules/jit/cache-tests
@@ -31,4 +31,4 @@ TESTS += test-cache
 check_PROGRAMS += test-cache
 test_cache_SOURCES = jit/test-cache.c
 test_cache_CFLAGS = $(AM_CFLAGS) $(DISABLE_OPENBSD_RETGUARD)
-test_cache_LDADD = $(LDADD) $(LIBINTL) @LIBDL@
+test_cache_LDADD = $(LDADD) $(LIBINTL) $(PTHREAD_SIGMASK_LIB) @LIBDL@




Reply via email to