bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

fatal-signal: make multithread-safe


From: Bruno Haible
Subject: fatal-signal: make multithread-safe
Date: Sat, 27 Jun 2020 23:57:48 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-179-generic; KDE/5.18.0; x86_64; ; )

2020-06-27  Bruno Haible  <bruno@clisp.org>

        fatal-signal: Make multithread-safe.
        * lib/fatal-signal.c: Include glthread/lock.h.
        (at_fatal_signal_lock): New variable.
        (at_fatal_signal): Use it.
        (fatal_signals_block_lock, fatal_signals_block_counter): New variables.
        (block_fatal_signals, unblock_fatal_signals): Use them.
        * modules/fatal-signal (Depends-on): Add lock.

diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index c8ff338..975393b 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -26,6 +26,7 @@
 #include <signal.h>
 #include <unistd.h>
 
+#include "glthread/lock.h"
 #include "sig-handler.h"
 #include "xalloc.h"
 
@@ -200,11 +201,16 @@ install_handlers (void)
 }
 
 
+/* Lock that makes at_fatal_signal multi-thread safe.  */
+gl_lock_define_initialized (static, at_fatal_signal_lock)
+
 /* Register a cleanup function to be executed when a catchable fatal signal
    occurs.  */
 void
 at_fatal_signal (action_t action)
 {
+  gl_lock_lock (at_fatal_signal_lock);
+
   static bool cleanup_initialized = false;
   if (!cleanup_initialized)
     {
@@ -242,6 +248,8 @@ at_fatal_signal (action_t action)
      actions[actions_count].  */
   actions[actions_count].action = action;
   actions_count++;
+
+  gl_lock_unlock (at_fatal_signal_lock);
 }
 
 
@@ -269,20 +277,43 @@ init_fatal_signal_set (void)
     }
 }
 
+/* Lock and counter that allow block_fatal_signals/unblock_fatal_signals pairs
+   to occur in different threads and even overlap in time.  */
+gl_lock_define_initialized (static, fatal_signals_block_lock)
+static unsigned int fatal_signals_block_counter = 0;
+
 /* Temporarily delay the catchable fatal signals.  */
 void
 block_fatal_signals (void)
 {
-  init_fatal_signal_set ();
-  sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
+  gl_lock_lock (fatal_signals_block_lock);
+
+  if (fatal_signals_block_counter++ == 0)
+    {
+      init_fatal_signal_set ();
+      sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
+    }
+
+  gl_lock_unlock (fatal_signals_block_lock);
 }
 
 /* Stop delaying the catchable fatal signals.  */
 void
 unblock_fatal_signals (void)
 {
-  init_fatal_signal_set ();
-  sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
+  gl_lock_lock (fatal_signals_block_lock);
+
+  if (fatal_signals_block_counter == 0)
+    /* There are more calls to unblock_fatal_signals() than to
+       block_fatal_signals().  */
+    abort ();
+  if (--fatal_signals_block_counter == 0)
+    {
+      init_fatal_signal_set ();
+      sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
+    }
+
+  gl_lock_unlock (fatal_signals_block_lock);
 }
 
 
diff --git a/modules/fatal-signal b/modules/fatal-signal
index 6683c79..de53de7 100644
--- a/modules/fatal-signal
+++ b/modules/fatal-signal
@@ -12,6 +12,7 @@ xalloc
 stdbool
 unistd
 sigaction
+lock
 sigprocmask
 raise
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]