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>
 
 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.
        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"
 
 #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
 # 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);
       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;
        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;
 {
   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;
   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;
 
   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");
 
   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
 # else
-    return signal (SIGSEGV, die) == SIG_ERR ? -1 : 0;
+  act.sa_flags = SA_NODEFER | SA_RESETHAND;
+  act.sa_handler = die;
 # endif
 # endif
-  }
+
+  return sigaction (SIGSEGV, &act, NULL);
 }
 
 #else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
 }
 
 #else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
index 7654d1f..eca46db 100644 (file)
 #include <signal.h>
 #include <unistd.h>
 
 #include <signal.h>
 #include <unistd.h>
 
+#include "sig-handler.h"
 #include "xalloc.h"
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 
 #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)
     {
   static bool fatal_signals_initialized = false;
   if (!fatal_signals_initialized)
     {
-#if HAVE_SIGACTION
       size_t i;
 
       for (i = 0; i < num_fatal_signals; i++)
       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
          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;
        }
            fatal_signals[i] = -1;
        }
-#endif
 
       fatal_signals_initialized = true;
     }
 
       fatal_signals_initialized = true;
     }
@@ -136,10 +130,14 @@ static inline void
 uninstall_handlers ()
 {
   size_t i;
 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)
   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.
     }
 
   /* 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);
 }
   uninstall_handlers ();
   raise (sig);
 }
@@ -175,10 +173,16 @@ static inline void
 install_handlers ()
 {
   size_t i;
 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)
   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 <time.h>
 
+#include "sig-handler.h"
 #include "timespec.h"
 
 #include <stdbool.h>
 #include "timespec.h"
 
 #include <stdbool.h>
@@ -102,10 +103,6 @@ rpl_nanosleep (const struct timespec *requested_delay,
 #  define SIGCONT SIGTERM
 # endif
 
 #  define SIGCONT SIGTERM
 # endif
 
-# if ! HAVE_SIGINTERRUPT
-#  define siginterrupt(sig, flag) /* empty */
-# endif
-
 static sig_atomic_t volatile suspended;
 
 /* Handle SIGCONT. */
 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)
     {
   /* 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);
       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);
        sigaction (SIGCONT, &newact, NULL);
-# else
-      if (signal (SIGCONT, SIG_IGN) != SIG_IGN)
-       {
-         signal (SIGCONT, sighandler);
-         siginterrupt (SIGCONT, 1);
-       }
-# endif
       initialized = true;
     }
 
       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 <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,
 /* 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
 
 # define SIGSTOP (-1)
 #endif
 
-/* A signal handler.  */
-typedef void (*handler_t) (int signal);
-
 int
 sigismember (const sigset_t *set, int sig)
 {
 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.  */
 
 /* 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)
 
 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.  */
 
 /* 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.  */
 {
   /* 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.  */
             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;
        }
          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
 
 
 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,
 
 # 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],
 [
 # Prerequisites of lib/nanosleep.c.
 AC_DEFUN([gl_PREREQ_NANOSLEEP],
 [
-  AC_CHECK_FUNCS_ONCE(siginterrupt)
   AC_CHECK_HEADERS_ONCE(sys/select.h)
 ])
   AC_CHECK_HEADERS_ONCE(sys/select.h)
 ])
index e87dd1a..d3e7e09 100644 (file)
@@ -11,6 +11,7 @@ gettext-h
 exitfail
 unistd
 raise
 exitfail
 unistd
 raise
+sigaction
 
 configure.ac:
 gl_C_STACK
 
 configure.ac:
 gl_C_STACK
index 8e8eb8a..296fbd3 100644 (file)
@@ -11,6 +11,7 @@ Depends-on:
 xalloc
 stdbool
 unistd
 xalloc
 stdbool
 unistd
+sigaction
 sigprocmask
 raise
 
 sigprocmask
 raise
 
index 3ff486e..61b4527 100644 (file)
@@ -9,6 +9,7 @@ Depends-on:
 clock-time
 extensions
 gettime
 clock-time
 extensions
 gettime
+sigaction
 stdbool
 sys_select
 sys_time
 stdbool
 sys_select
 sys_time
index 60c0e8c..8490573 100644 (file)
@@ -3,6 +3,7 @@ POSIX compatible signal handlers.
 
 Files:
 lib/sigaction.c
 
 Files:
 lib/sigaction.c
+lib/sig-handler.h
 m4/sigaction.m4
 
 Depends-on:
 m4/sigaction.m4
 
 Depends-on:
index e093112..37adc63 100644 (file)
@@ -3,6 +3,7 @@ POSIX compatible signal blocking.
 
 Files:
 lib/sigprocmask.c
 
 Files:
 lib/sigprocmask.c
+lib/sig-handler.h
 m4/signalblocking.m4
 
 Depends-on:
 m4/signalblocking.m4
 
 Depends-on: