Tests for module 'unicase/u16-is-uppercase'.
[gnulib.git] / lib / fatal-signal.c
index eca46db..df9e011 100644 (file)
@@ -125,19 +125,25 @@ static sig_atomic_t volatile actions_count = 0;
 static size_t actions_allocated = SIZEOF (static_actions);
 
 
+/* The saved signal handlers.
+   Size 32 would not be sufficient: On HP-UX, SIGXCPU = 33, SIGXFSZ = 34.  */
+static struct sigaction saved_sigactions[64];
+
+
 /* Uninstall the handlers.  */
 static inline void
 uninstall_handlers ()
 {
   size_t i;
-  struct sigaction action;
 
-  action.sa_handler = SIG_DFL;
-  action.sa_flags = 0;
-  sigemptyset (&action.sa_mask);
   for (i = 0; i < num_fatal_signals; i++)
     if (fatal_signals[i] >= 0)
-      sigaction (fatal_signals[i], &action, NULL);
+      {
+       int sig = fatal_signals[i];
+       if (saved_sigactions[sig].sa_handler == SIG_IGN)
+         saved_sigactions[sig].sa_handler = SIG_DFL;
+       sigaction (sig, &saved_sigactions[sig], NULL);
+      }
 }
 
 
@@ -160,9 +166,10 @@ fatal_signal_handler (int sig)
     }
 
   /* Now execute the signal's default action.
-     If any cleanup action blocks the signal that triggered the cleanup, the
-     re-raised signal is delivered when this handler returns; otherwise it
-     is delivered already during raise().  */
+     If the signal being delivered was blocked, the re-raised signal would be
+     delivered when this handler returns.  But the way we install this handler,
+     no signal is blocked, and the re-raised signal is delivered already
+     during raise().  */
   uninstall_handlers ();
   raise (sig);
 }
@@ -176,13 +183,20 @@ install_handlers ()
   struct sigaction action;
 
   action.sa_handler = &fatal_signal_handler;
-  /* One-shot handling - if we fault while handling a fault, the
-     cleanup actions are intentionally cut short.  */
-  action.sa_flags = SA_NODEFER | SA_RESETHAND;
+  /* If we get a fatal signal while executing fatal_signal_handler, enter
+     fatal_signal_handler recursively, since it is reentrant.  Hence no
+     SA_RESETHAND.  */
+  action.sa_flags = SA_NODEFER;
   sigemptyset (&action.sa_mask);
   for (i = 0; i < num_fatal_signals; i++)
     if (fatal_signals[i] >= 0)
-      sigaction (fatal_signals[i], &action, NULL);
+      {
+       int sig = fatal_signals[i];
+
+       if (!(sig < sizeof (saved_sigactions) / sizeof (saved_sigactions[0])))
+         abort ();
+       sigaction (sig, &action, &saved_sigactions[sig]);
+      }
 }