Use sigaction module rather than signal().
authorEric Blake <ebb9@byu.net>
Sat, 21 Jun 2008 13:08:49 +0000 (07:08 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 21 Jun 2008 20:56:08 +0000 (14:56 -0600)
* modules/c-stack (Depends-on): Add sigaction.
* modules/fatal-signal (Depends-on): Likewise.
* modules/nanosleep (Depends-on): Likewise.
* modules/sigprocmask (Files): Add sig-handler.h.
* modules/sigaction (Files): Likewise.
* lib/sig-handler.h (get_handler): New file, suggested by Paul
Eggert.
* lib/c-stack.c (SIGACTION_WORKS): Simplify conditions.
(c_stack_action) [!SIGACTION_WORKS]: Use sigaction, not signal.
* lib/fatal-signal.c (uninstall_handlers, install_handlers)
(init_fatal_signals): Likewise.
* lib/nanosleep.c (rpl_nanosleep): Likewise.
(siginterrupt): Delete fallback.
* lib/sigprocmask.c (handler_t): Delete.
(old_handlers): Use sa_handler_t instead.
* m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for
siginterrupt.

Signed-off-by: Eric Blake <ebb9@byu.net>
12 files changed:
ChangeLog
lib/c-stack.c
lib/fatal-signal.c
lib/nanosleep.c
lib/sig-handler.h [new file with mode: 0644]
lib/sigprocmask.c
m4/nanosleep.m4
modules/c-stack
modules/fatal-signal
modules/nanosleep
modules/sigaction
modules/sigprocmask

index e3b0279..dcb8f5e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2008-06-21  Eric Blake  <ebb9@byu.net>
 
+       Use sigaction module rather than signal().
+       * modules/c-stack (Depends-on): Add sigaction.
+       * modules/fatal-signal (Depends-on): Likewise.
+       * modules/nanosleep (Depends-on): Likewise.
+       * modules/sigprocmask (Files): Add sig-handler.h.
+       * modules/sigaction (Files): Likewise.
+       * lib/sig-handler.h (get_handler): New file, suggested by Paul
+       Eggert.
+       * lib/c-stack.c (SIGACTION_WORKS): Simplify conditions.
+       (c_stack_action) [!SIGACTION_WORKS]: Use sigaction, not signal.
+       * lib/fatal-signal.c (uninstall_handlers, install_handlers)
+       (init_fatal_signals): Likewise.
+       * lib/nanosleep.c (rpl_nanosleep): Likewise.
+       (siginterrupt): Delete fallback.
+       * lib/sigprocmask.c (handler_t, old_handlers): Use sa_handler_t
+       instead.
+       * m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for
+       siginterrupt.
+
        New module sigaction, for mingw.
        * modules/sigaction: New module...
        * modules/sigaction-tests: ...and its test.
index ff892c5..96bd2bf 100644 (file)
@@ -71,8 +71,7 @@ typedef struct sigaltstack stack_t;
 #include "c-stack.h"
 #include "exitfail.h"
 
-#if (HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined SA_NODEFER \
-     && defined SA_ONSTACK && defined SA_RESETHAND && defined SA_SIGINFO)
+#if defined SA_ONSTACK && defined SA_SIGINFO
 # define SIGACTION_WORKS 1
 #else
 # define SIGACTION_WORKS 0
@@ -168,7 +167,7 @@ segv_handler (int signo, siginfo_t *info,
       char const *faulting_address = info->si_addr;
       size_t s = faulting_address - stack_base;
       size_t page_size = sysconf (_SC_PAGESIZE);
-      if (find_stack_direction (0) < 0)
+      if (find_stack_direction (NULL) < 0)
        s += page_size;
       if (s < stack_size + page_size)
        signo = 0;
@@ -213,10 +212,11 @@ c_stack_action (void (*action) (int))
 {
   int r;
   stack_t st;
+  struct sigaction act;
   st.ss_flags = 0;
   st.ss_sp = alternate_signal_stack.buffer;
   st.ss_size = sizeof alternate_signal_stack.buffer;
-  r = sigaltstack (&st, 0);
+  r = sigaltstack (&st, NULL);
   if (r != 0)
     return r;
 
@@ -224,23 +224,20 @@ c_stack_action (void (*action) (int))
   program_error_message = _("program error");
   stack_overflow_message = _("stack overflow");
 
-  {
-# if SIGACTION_WORKS
-    struct sigaction act;
-    sigemptyset (&act.sa_mask);
-
-    /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but
-       this is not true on Solaris 8 at least.  It doesn't hurt to use
-       SA_NODEFER here, so leave it in.  */
-    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
-
-    act.sa_sigaction = segv_handler;
+  sigemptyset (&act.sa_mask);
 
-    return sigaction (SIGSEGV, &act, 0);
+# if SIGACTION_WORKS
+  /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but
+     this is not true on Solaris 8 at least.  It doesn't hurt to use
+     SA_NODEFER here, so leave it in.  */
+  act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
+  act.sa_sigaction = segv_handler;
 # else
-    return signal (SIGSEGV, die) == SIG_ERR ? -1 : 0;
+  act.sa_flags = SA_NODEFER | SA_RESETHAND;
+  act.sa_handler = die;
 # endif
-  }
+
+  return sigaction (SIGSEGV, &act, NULL);
 }
 
 #else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
index 7654d1f..eca46db 100644 (file)
 #include <signal.h>
 #include <unistd.h>
 
+#include "sig-handler.h"
 #include "xalloc.h"
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 
-
 /* ========================================================================= */
 
 
@@ -88,7 +88,6 @@ init_fatal_signals (void)
   static bool fatal_signals_initialized = false;
   if (!fatal_signals_initialized)
     {
-#if HAVE_SIGACTION
       size_t i;
 
       for (i = 0; i < num_fatal_signals; i++)
@@ -96,14 +95,9 @@ init_fatal_signals (void)
          struct sigaction action;
 
          if (sigaction (fatal_signals[i], NULL, &action) >= 0
-             /* POSIX says that SIG_IGN can only occur when action.sa_flags
-                does not contain SA_SIGINFO.  But in Linux 2.4, for example,
-                SA_SIGINFO can actually be set and is ignored when sa_handler
-                is SIG_IGN.  So don't bother testing for SA_SIGINFO.  */
-             && action.sa_handler == SIG_IGN)
+             && get_handler (&action) == SIG_IGN)
            fatal_signals[i] = -1;
        }
-#endif
 
       fatal_signals_initialized = true;
     }
@@ -136,10 +130,14 @@ 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)
-      signal (fatal_signals[i], SIG_DFL);
+      sigaction (fatal_signals[i], &action, NULL);
 }
 
 
@@ -162,9 +160,9 @@ fatal_signal_handler (int sig)
     }
 
   /* Now execute the signal's default action.
-     If signal() blocks the signal being delivered for the duration of the
-     signal handler's execution, the re-raised signal is delivered when this
-     handler returns; otherwise it is delivered already during raise().  */
+     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().  */
   uninstall_handlers ();
   raise (sig);
 }
@@ -175,10 +173,16 @@ static inline void
 install_handlers ()
 {
   size_t i;
+  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;
+  sigemptyset (&action.sa_mask);
   for (i = 0; i < num_fatal_signals; i++)
     if (fatal_signals[i] >= 0)
-      signal (fatal_signals[i], &fatal_signal_handler);
+      sigaction (fatal_signals[i], &action, NULL);
 }
 
 
index 1239cb0..1732c59 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <time.h>
 
+#include "sig-handler.h"
 #include "timespec.h"
 
 #include <stdbool.h>
@@ -102,10 +103,6 @@ rpl_nanosleep (const struct timespec *requested_delay,
 #  define SIGCONT SIGTERM
 # endif
 
-# if ! HAVE_SIGINTERRUPT
-#  define siginterrupt(sig, flag) /* empty */
-# endif
-
 static sig_atomic_t volatile suspended;
 
 /* Handle SIGCONT. */
@@ -150,22 +147,14 @@ rpl_nanosleep (const struct timespec *requested_delay,
   /* set up sig handler */
   if (! initialized)
     {
-# ifdef SA_NOCLDSTOP
       struct sigaction oldact, newact;
       newact.sa_handler = sighandler;
       sigemptyset (&newact.sa_mask);
       newact.sa_flags = 0;
 
       sigaction (SIGCONT, NULL, &oldact);
-      if (oldact.sa_handler != SIG_IGN)
+      if (get_handler (&oldact) != SIG_IGN)
        sigaction (SIGCONT, &newact, NULL);
-# else
-      if (signal (SIGCONT, SIG_IGN) != SIG_IGN)
-       {
-         signal (SIGCONT, sighandler);
-         siginterrupt (SIGCONT, 1);
-       }
-# endif
       initialized = true;
     }
 
diff --git a/lib/sig-handler.h b/lib/sig-handler.h
new file mode 100644 (file)
index 0000000..969f679
--- /dev/null
@@ -0,0 +1,44 @@
+/* Convenience declarations when working with <signal.h>.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GL_SIG_HANDLER_H
+#define _GL_SIG_HANDLER_H
+
+#include <signal.h>
+
+/* Convenience type when working with signal handlers.  */
+typedef void (*sa_handler_t) (int);
+
+/* Return the handler of a signal, as a sa_handler_t value regardless
+   of its true type.  The resulting function can be compared to
+   special values like SIG_IGN but it is not portable to call it.  */
+static inline sa_handler_t
+get_handler (struct sigaction const *a)
+{
+#ifdef SA_SIGINFO
+  /* POSIX says that special values like SIG_IGN can only occur when
+     action.sa_flags does not contain SA_SIGINFO.  But in Linux 2.4,
+     for example, sa_sigaction and sa_handler are aliases and a signal
+     is ignored if sa_sigaction (after casting) equals SIG_IGN.  So
+     use (and cast) sa_sigaction in that case.  */
+  if (a->sa_flags & SA_SIGINFO)
+    return (sa_handler_t) a->sa_sigaction;
+#endif
+  return a->sa_handler;
+}
+
+#endif /* _GL_SIG_HANDLER_H */
index 87d585c..a8f2eb4 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include "sig-handler.h"
+
 /* We assume that a platform without POSIX signal blocking functions
    also does not have the POSIX sigaction() function, only the
    signal() function.  We also assume signal() has SysV semantics,
@@ -43,9 +45,6 @@
 # define SIGSTOP (-1)
 #endif
 
-/* A signal handler.  */
-typedef void (*handler_t) (int signal);
-
 int
 sigismember (const sigset_t *set, int sig)
 {
@@ -134,7 +133,7 @@ sigpending (sigset_t *set)
 
 /* The previous signal handlers.
    Only the array elements corresponding to blocked signals are relevant.  */
-static volatile handler_t old_handlers[NSIG];
+static volatile sa_handler_t old_handlers[NSIG];
 
 int
 sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
@@ -208,8 +207,8 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
 
 /* Install the handler FUNC for signal SIG, and return the previous
    handler.  */
-handler_t
-rpl_signal (int sig, handler_t handler)
+sa_handler_t
+rpl_signal (int sig, sa_handler_t handler)
 {
   /* We must provide a wrapper, so that a user can query what handler
      they installed even if that signal is currently blocked.  */
@@ -227,7 +226,7 @@ rpl_signal (int sig, handler_t handler)
             stale information if it calls signal(B).  Oh well -
             signal handlers really shouldn't try to manipulate the
             installed handlers of unrelated signals.  */
-         handler_t result = old_handlers[sig];
+         sa_handler_t result = old_handlers[sig];
          old_handlers[sig] = handler;
          return result;
        }
index 1d832a3..8780921 100644 (file)
@@ -1,12 +1,12 @@
-#serial 23
+#serial 24
 
 dnl From Jim Meyering.
 dnl Check for the nanosleep function.
 dnl If not found, use the supplied replacement.
 dnl
 
-# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 Free
-# Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -111,6 +111,5 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
 # Prerequisites of lib/nanosleep.c.
 AC_DEFUN([gl_PREREQ_NANOSLEEP],
 [
-  AC_CHECK_FUNCS_ONCE(siginterrupt)
   AC_CHECK_HEADERS_ONCE(sys/select.h)
 ])
index e87dd1a..d3e7e09 100644 (file)
@@ -11,6 +11,7 @@ gettext-h
 exitfail
 unistd
 raise
+sigaction
 
 configure.ac:
 gl_C_STACK
index 8e8eb8a..296fbd3 100644 (file)
@@ -11,6 +11,7 @@ Depends-on:
 xalloc
 stdbool
 unistd
+sigaction
 sigprocmask
 raise
 
index 3ff486e..61b4527 100644 (file)
@@ -9,6 +9,7 @@ Depends-on:
 clock-time
 extensions
 gettime
+sigaction
 stdbool
 sys_select
 sys_time
index 60c0e8c..8490573 100644 (file)
@@ -3,6 +3,7 @@ POSIX compatible signal handlers.
 
 Files:
 lib/sigaction.c
+lib/sig-handler.h
 m4/sigaction.m4
 
 Depends-on:
index e093112..37adc63 100644 (file)
@@ -3,6 +3,7 @@ POSIX compatible signal blocking.
 
 Files:
 lib/sigprocmask.c
+lib/sig-handler.h
 m4/signalblocking.m4
 
 Depends-on: