* 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>
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.
#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
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;
{
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;
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) */
#include <signal.h>
#include <unistd.h>
+#include "sig-handler.h"
#include "xalloc.h"
#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
-
/* ========================================================================= */
static bool fatal_signals_initialized = false;
if (!fatal_signals_initialized)
{
-#if HAVE_SIGACTION
size_t i;
for (i = 0; i < num_fatal_signals; i++)
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;
}
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);
}
}
/* 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);
}
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);
}
#include <time.h>
+#include "sig-handler.h"
#include "timespec.h"
#include <stdbool.h>
# define SIGCONT SIGTERM
# endif
-# if ! HAVE_SIGINTERRUPT
-# define siginterrupt(sig, flag) /* empty */
-# endif
-
static sig_atomic_t volatile suspended;
/* Handle SIGCONT. */
/* 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;
}
--- /dev/null
+/* 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 */
#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,
# define SIGSTOP (-1)
#endif
-/* A signal handler. */
-typedef void (*handler_t) (int signal);
-
int
sigismember (const sigset_t *set, int sig)
{
/* 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)
/* 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. */
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;
}
-#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,
# Prerequisites of lib/nanosleep.c.
AC_DEFUN([gl_PREREQ_NANOSLEEP],
[
- AC_CHECK_FUNCS_ONCE(siginterrupt)
AC_CHECK_HEADERS_ONCE(sys/select.h)
])
exitfail
unistd
raise
+sigaction
configure.ac:
gl_C_STACK
xalloc
stdbool
unistd
+sigaction
sigprocmask
raise
clock-time
extensions
gettime
+sigaction
stdbool
sys_select
sys_time
Files:
lib/sigaction.c
+lib/sig-handler.h
m4/sigaction.m4
Depends-on:
Files:
lib/sigprocmask.c
+lib/sig-handler.h
m4/signalblocking.m4
Depends-on: