From 4b2f21b36a615728ebf2a0e1bc2c8def175703a8 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 21 Jun 2008 07:08:49 -0600 Subject: [PATCH] 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): Delete. (old_handlers): Use sa_handler_t instead. * m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for siginterrupt. Signed-off-by: Eric Blake --- ChangeLog | 19 +++++++++++++++++++ lib/c-stack.c | 33 +++++++++++++++------------------ lib/fatal-signal.c | 30 +++++++++++++++++------------- lib/nanosleep.c | 15 ++------------- lib/sig-handler.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib/sigprocmask.c | 13 ++++++------- m4/nanosleep.m4 | 7 +++---- modules/c-stack | 1 + modules/fatal-signal | 1 + modules/nanosleep | 1 + modules/sigaction | 1 + modules/sigprocmask | 1 + 12 files changed, 111 insertions(+), 55 deletions(-) create mode 100644 lib/sig-handler.h diff --git a/ChangeLog b/ChangeLog index e3b0279d4..dcb8f5e59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2008-06-21 Eric Blake + 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. diff --git a/lib/c-stack.c b/lib/c-stack.c index ff892c5eb..96bd2bf60 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -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) */ diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index 7654d1f4f..eca46dba0 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -26,11 +26,11 @@ #include #include +#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); } diff --git a/lib/nanosleep.c b/lib/nanosleep.c index 1239cb033..1732c599b 100644 --- a/lib/nanosleep.c +++ b/lib/nanosleep.c @@ -22,6 +22,7 @@ #include +#include "sig-handler.h" #include "timespec.h" #include @@ -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 index 000000000..969f67902 --- /dev/null +++ b/lib/sig-handler.h @@ -0,0 +1,44 @@ +/* Convenience declarations when working with . + + 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 . */ + +#ifndef _GL_SIG_HANDLER_H +#define _GL_SIG_HANDLER_H + +#include + +/* 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 */ diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c index 87d585c94..a8f2eb4e3 100644 --- a/lib/sigprocmask.c +++ b/lib/sigprocmask.c @@ -24,6 +24,8 @@ #include #include +#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; } diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4 index 1d832a3e5..87809219d 100644 --- a/m4/nanosleep.m4 +++ b/m4/nanosleep.m4 @@ -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) ]) diff --git a/modules/c-stack b/modules/c-stack index e87dd1ad6..d3e7e0996 100644 --- a/modules/c-stack +++ b/modules/c-stack @@ -11,6 +11,7 @@ gettext-h exitfail unistd raise +sigaction configure.ac: gl_C_STACK diff --git a/modules/fatal-signal b/modules/fatal-signal index 8e8eb8a6d..296fbd301 100644 --- a/modules/fatal-signal +++ b/modules/fatal-signal @@ -11,6 +11,7 @@ Depends-on: xalloc stdbool unistd +sigaction sigprocmask raise diff --git a/modules/nanosleep b/modules/nanosleep index 3ff486e81..61b4527b3 100644 --- a/modules/nanosleep +++ b/modules/nanosleep @@ -9,6 +9,7 @@ Depends-on: clock-time extensions gettime +sigaction stdbool sys_select sys_time diff --git a/modules/sigaction b/modules/sigaction index 60c0e8c0f..849057395 100644 --- a/modules/sigaction +++ b/modules/sigaction @@ -3,6 +3,7 @@ POSIX compatible signal handlers. Files: lib/sigaction.c +lib/sig-handler.h m4/sigaction.m4 Depends-on: diff --git a/modules/sigprocmask b/modules/sigprocmask index e09311203..37adc63d3 100644 --- a/modules/sigprocmask +++ b/modules/sigprocmask @@ -3,6 +3,7 @@ POSIX compatible signal blocking. Files: lib/sigprocmask.c +lib/sig-handler.h m4/signalblocking.m4 Depends-on: -- 2.11.0