bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: sigaction module


From: Eric Blake
Subject: RFC: sigaction module
Date: Mon, 16 Jun 2008 22:38:59 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

In trying to use c-stack in m4, I found it annoying to support both signal and 
sigaction everywhere, particularly since Posix states that signal() should be 
avoided in portable programs because of its unspecified handling of signal 
masks and handler reset.  Mingw is the biggest culprit, although I'm not sure 
if other platforms exist where sigaction is lacking (Bruno's documentation in 
doc/posix-functions mentioned a larger list of platforms lacking siginterrupt 
than sigaction).  Note that even though a lacking siginterrupt could be 
implemented via a fully-compliant sigaction, I'm intentionally not doing that 
(no need to implement functions like siginterrupt where Posix points to 
sigaction in the first place).

I've gone ahead and done an reduced implementation of sigaction for mingw, 
getting the parts that were easy to implement and which were exercised within 
other gnulib modules.  The implementation is NOT async-signal-safe, but since 
it seems that mingw is the only platform lacking a native sigaction, this does 
not seem to be much of a loss (after all, mingw's signal(2) semantics are 
somewhat limited - it supports definitions only for SIGBREAK and the six 
signals required by C89, but mentions in /usr/include/signal.h that SIGILL is 
untested and SIGFPE doesn't work; it also lacks kill(1)/kill(2) for sending 
asynchronous signals in the first place).

Does anyone see any problems with these patches, or should I go ahead and 
commit so we can get wider test coverage?

>From a5cccc4692a455613b7bf3a666150f878e1b738b Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Mon, 16 Jun 2008 14:58:28 -0600
Subject: [PATCH] New module sigaction, for mingw.

* modules/sigaction: New module.
* m4/sigaction.m4: New file.
* m4/signal_h.m4 (gl_SIGNAL_H_DEFAULTS): Add sigaction variables.
* modules/signal (Makefile.am): Likewise.
* doc/posix-headers/signal.texi (signal.h): Mention provided
types.
* doc/posix-functions/siginterrupt.texi (siginterrupt): Mention
that sigaction is preferable.
* doc/posix-functions/sigaction.texi (sigaction): Mention new
module.
* MODULES.html.sh (Support for systems lacking POSIX:2001): Add
sigaction.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                             |   14 ++++
 MODULES.html.sh                       |    1 +
 doc/posix-functions/sigaction.texi    |   25 ++++++-
 doc/posix-functions/siginterrupt.texi |    3 +
 doc/posix-headers/signal.texi         |   10 ++-
 lib/sigaction.c                       |  136 +++++++++++++++++++++++++++++++++
 lib/signal.in.h                       |   56 +++++++++++++-
 m4/sigaction.m4                       |   34 ++++++++
 m4/signal_h.m4                        |    7 +-
 modules/sigaction                     |   25 ++++++
 modules/sigaction-tests               |   11 +++
 modules/signal                        |    3 +
 tests/test-sigaction.c                |   88 +++++++++++++++++++++
 13 files changed, 406 insertions(+), 7 deletions(-)
 create mode 100644 lib/sigaction.c
 create mode 100644 m4/sigaction.m4
 create mode 100644 modules/sigaction
 create mode 100644 modules/sigaction-tests
 create mode 100644 tests/test-sigaction.c

diff --git a/ChangeLog b/ChangeLog
index 054cec0..ad7c04c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2008-06-16  Eric Blake  <address@hidden>
 
+       New module sigaction, for mingw.
+       * modules/sigaction: New module.
+       * m4/sigaction.m4: New file.
+       * m4/signal_h.m4 (gl_SIGNAL_H_DEFAULTS): Add sigaction variables.
+       * modules/signal (Makefile.am): Likewise.
+       * doc/posix-headers/signal.texi (signal.h): Mention provided
+       types.
+       * doc/posix-functions/siginterrupt.texi (siginterrupt): Mention
+       that sigaction is preferable.
+       * doc/posix-functions/sigaction.texi (sigaction): Mention new
+       module.
+       * MODULES.html.sh (Support for systems lacking POSIX:2001): Add
+       sigaction.
+
        Fix compliance bug in sigpending.
        * lib/sigprocmask.c (sigpending): Return pending array via
        parameter, not return value.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index f82e957..8f3aa4f 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2131,6 +2131,7 @@ func_all_modules ()
   func_module rename
   func_module rmdir
   func_module search
+  func_module sigaction
   func_module sigprocmask
   func_module socklen
   func_module ssize_t
diff --git a/doc/posix-functions/sigaction.texi b/doc/posix-
functions/sigaction.texi
index 80e3b2c..62cf774 100644
--- a/doc/posix-functions/sigaction.texi
+++ b/doc/posix-functions/sigaction.texi
@@ -4,17 +4,38 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xsh/sigaction.html}
 
-Gnulib module: ---
+Gnulib module: sigaction
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This function is missing on some platforms:
+mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
-This function is missing on some platforms:
+Posix recommends that when specifying SA_RESETHAND, SA_NODEFER must
+also be specified.
+
address@hidden
+Support for SA_ONSTACK is missing on some platforms:
+mingw, cygwin.
+
address@hidden
+Support for SA_SIGINFO is missing on some platforms:
 mingw.
+
address@hidden
+Support for SIGCHLD, and thus for SA_NOCLDSTOP and SA_NOCLDWAIT, is
+missing on some platforms:
+mingw.
+
address@hidden
+Support for SA_RESTART is missing on some platforms:
+mingw.
+
 @item
 The symbolic value @code{SIG_IGN} for the @code{SIGCHLD} signal is equivalent
 to a signal handler
diff --git a/doc/posix-functions/siginterrupt.texi b/doc/posix-
functions/siginterrupt.texi
index 48223ab..07d070c 100644
--- a/doc/posix-functions/siginterrupt.texi
+++ b/doc/posix-functions/siginterrupt.texi
@@ -15,4 +15,7 @@ Portability problems not fixed by Gnulib:
 @item
 This function is missing on some platforms:
 Solaris 2.5.1, mingw, Interix 3.5, BeOS.
+
address@hidden
+Posix recommends using @code{sigaction} with SA_NODEFER instead.
 @end itemize
diff --git a/doc/posix-headers/signal.texi b/doc/posix-headers/signal.texi
index 272e646..c7981cf 100644
--- a/doc/posix-headers/signal.texi
+++ b/doc/posix-headers/signal.texi
@@ -3,10 +3,18 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xbd/signal.h.html}
 
-Gnulib module: ---
+Gnulib module: signal
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
address@hidden is only declared in <sys/types.h> on some platforms:
+mingw.
+
address@hidden
address@hidden sigaction} and @code{siginfo_t} are missing on some
+platforms:
+mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/sigaction.c b/lib/sigaction.c
new file mode 100644
index 0000000..a5ffde7
--- /dev/null
+++ b/lib/sigaction.c
@@ -0,0 +1,136 @@
+/* POSIX compatible signal blocking.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Written by Eric Blake <address@hidden>, 2008.
+
+   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/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <signal.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* We assume that a platform without POSIX sigaction implements SysV
+   semantics in signal() (ie. the handler is uninstalled before it is
+   invoked).  This is an inherent data race, but there's nothing we
+   can do about it.  We assume that SIGCHLD is not defined, so we
+   don't implement SA_NOCLDSTOP or SA_NOCLDWAIT.  We assume that
+   sigaltstack() is not present, so we don't implement SA_ONSTACK.  We
+   assume siginterrupt() is not present, so we don't implement
+   SA_RESTART.  Supporting SA_SIGINFO is impossible to do portably.
+   These points are true for Woe32 platforms.
+
+   SysV semantics are already unsafe in the presence of asynchronous
+   signals; we compound the situation by reading static memory in
+   signal handlers.  Oh well.  */
+
+#ifndef SIGKILL
+# define SIGKILL (-1)
+#endif
+#ifndef SIGSTOP
+# define SIGSTOP (-1)
+#endif
+
+/* A signal handler.  */
+typedef void (*handler_t) (int signal);
+
+/* Set of current actions.  */
+static struct sigaction action_array[NSIG] /* = 0 */;
+
+/* Signal handler that is installed for signals.  */
+static void
+sigaction_handler (int sig)
+{
+  handler_t h;
+  sigset_t oldmask;
+  sigset_t mask;
+  if (sig < 0 || NSIG <= sig || !action_array[sig].sa_handler)
+    {
+      /* Unexpected situation; be careful to avoid recursive abort.  */
+      if (sig == SIGABRT)
+        exit (1);
+      abort ();
+    }
+
+  /* Reinstall the signal handler when required.  Do this prior to
+     blocking any signals, since sigprocmask replacement doesn't like
+     changing a blocked signal.  */
+  h = action_array[sig].sa_handler;
+  if ((action_array[sig].sa_flags & SA_RESETHAND) == 0)
+    signal (sig, sigaction_handler);
+  else
+    action_array[sig].sa_handler = NULL;
+
+  /* Block appropriate signals.  */
+  mask = action_array[sig].sa_mask;
+  if ((action_array[sig].sa_flags & SA_NODEFER) == 0)
+    sigaddset (&mask, sig);
+  sigprocmask (SIG_BLOCK, &mask, &oldmask);
+
+  /* Invoke the user's handler, then restore prior mask.  */
+  h (sig);
+  sigprocmask (SIG_SETMASK, &oldmask, NULL);
+}
+
+/* Change and/or query the action that will be taken on delivery of
+   signal SIG.  If not NULL, ACT describes the new behavior.  If not
+   NULL, OACT is set to the prior behavior.  Return 0 on success, or
+   set errno and return -1 on failure.  */
+int
+sigaction (int sig, const struct sigaction *restrict act,
+           struct sigaction *restrict oact)
+{
+  if (sig < 0 || NSIG <= sig || sig == SIGKILL || sig == SIGSTOP)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (oact)
+    {
+      if (action_array[sig].sa_handler)
+        *oact = action_array[sig];
+      else
+        {
+          /* This opens a slight window where an async signal can call
+             wrong handler.  Oh well.  */
+          oact->sa_handler = signal (sig, SIG_DFL);
+          signal (sig, oact->sa_handler);
+          if (oact->sa_handler == SIG_ERR)
+            return -1;
+          oact->sa_flags = SA_RESETHAND | SA_NODEFER;
+          sigemptyset (&oact->sa_mask);
+        }
+    }
+
+  if (act)
+    {
+      if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN)
+        {
+          if (signal (sig, act->sa_handler) == SIG_ERR)
+            return -1;
+          action_array[sig].sa_handler = NULL;
+        }
+      else
+        {
+          if (signal (sig, sigaction_handler) == SIG_ERR)
+            return -1;
+          action_array[sig] = *act;
+        }
+    }
+  return 0;
+}
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 9f82ba7..898cd0a 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <signal.h>.
 
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-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
@@ -85,7 +85,59 @@ extern int sigpending (sigset_t *set);
 # define SIG_UNBLOCK 2  /* blocked_set = blocked_set & ~*set; */
 extern int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set);
 
-#endif
+#endif /* address@hidden@ */
+
+#if address@hidden@
+
+# if address@hidden@
+/* Present to allow compilation, but unsupported by gnulib.  */
+union sigval
+{
+  int sival_int;
+  void *sival_ptr;
+};
+
+struct siginfo_t
+{
+  int si_signo;
+  int si_code;
+  int si_errno;
+  pid_t si_pid;
+  uid_t si_uid;
+  void *si_addr;
+  int si_status;
+  long si_band;
+  union sigval si_value;
+};
+typedef struct siginfo_t siginfo_t;
+# endif /* address@hidden@ */
+
+  /* Due to autoconf conventions, we can't tell if HAVE_SIGACTION
+     means we have the type or means we have the function.  We assume
+     that all implementations either have both or neither.  */
+
+struct sigaction
+{
+  union
+  {
+    void (*_sa_handler) (int);
+    /* Present to allow compilation, but unsupported by gnulib.  */
+    void (*_sa_sigaction) (int, siginfo_t *, void *);
+  } _sa_func;
+  sigset_t sa_mask;
+  /* Not all POSIX flags are supported.  */
+  int sa_flags;
+};
+# define sa_handler _sa_func._sa_handler
+# define sa_sigaction _sa_func._sa_sigaction
+/* Unsupported flags are not present.  */
+# define SA_RESETHAND 1
+# define SA_NODEFER 2
+
+extern int sigaction (int, const struct sigaction *restrict,
+                      struct sigaction *restrict);
+
+#endif /* address@hidden@ */
 
 
 #ifdef __cplusplus
diff --git a/m4/sigaction.m4 b/m4/sigaction.m4
new file mode 100644
index 0000000..43648e4
--- /dev/null
+++ b/m4/sigaction.m4
@@ -0,0 +1,34 @@
+# sigaction.m4 serial 1
+dnl Copyright (C) 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Determine if sigaction interface is present.
+AC_DEFUN([gl_SIGACTION],
+[
+  dnl Due to autoconf conventions, we can't tell if HAVE_SIGACTION
+  dnl means we have the type or means we have the function.  We assume
+  dnl that all implementations either have both or neither.
+  AC_REPLACE_FUNCS([sigaction])
+  if test $ac_cv_func_sigaction = no ; then
+    HAVE_SIGACTION=0
+    AC_SUBST([HAVE_SIGACTION])
+    gl_PREREQ_SIGACTION
+  fi
+])
+
+# Prerequisites of the part of lib/signal.in.h and of lib/sigprocmask.c.
+AC_DEFUN([gl_PREREQ_SIGACTION],
+[
+  AC_REQUIRE([AC_C_RESTRICT])
+  AC_REQUIRE([AC_TYPE_UID_T])
+  AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])
+  AC_CHECK_TYPES([siginfo_t], [], [], [[
+#include <signal.h>
+  ]])
+  if test $ac_cv_type_siginfo_t = no; then
+    HAVE_SIGINFO_T=0
+    AC_SUBST([HAVE_SIGINFO_T])
+  fi
+])
diff --git a/m4/signal_h.m4 b/m4/signal_h.m4
index 37ebca9..bf2bad4 100644
--- a/m4/signal_h.m4
+++ b/m4/signal_h.m4
@@ -1,5 +1,5 @@
-# signal_h.m4 serial 3
-dnl Copyright (C) 2007 Free Software Foundation, Inc.
+# signal_h.m4 serial 4
+dnl Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -20,7 +20,10 @@ AC_DEFUN([gl_SIGNAL_MODULE_INDICATOR],
 AC_DEFUN([gl_SIGNAL_H_DEFAULTS],
 [
   GNULIB_SIGPROCMASK=0;        AC_SUBST([GNULIB_SIGPROCMASK])
+  GNULIB_SIGACTION=0;          AC_SUBST([GNULIB_SIGACTION])
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE_POSIX_SIGNALBLOCKING=1; AC_SUBST([HAVE_POSIX_SIGNALBLOCKING])
   HAVE_SIGSET_T=1;             AC_SUBST([HAVE_SIGSET_T])
+  HAVE_SIGINFO_T=1;            AC_SUBST([HAVE_SIGINFO_T])
+  HAVE_SIGACTION=1;            AC_SUBST([HAVE_SIGACTION])
 ])
diff --git a/modules/sigaction b/modules/sigaction
new file mode 100644
index 0000000..60c0e8c
--- /dev/null
+++ b/modules/sigaction
@@ -0,0 +1,25 @@
+Description:
+POSIX compatible signal handlers.
+
+Files:
+lib/sigaction.c
+m4/sigaction.m4
+
+Depends-on:
+signal
+sigprocmask
+
+configure.ac:
+gl_SIGACTION
+gl_SIGNAL_MODULE_INDICATOR([sigaction])
+
+Makefile.am:
+
+Include:
+<signal.h>
+
+License:
+LGPL
+
+Maintainer:
+Eric Blake
diff --git a/modules/sigaction-tests b/modules/sigaction-tests
new file mode 100644
index 0000000..5a4f48f
--- /dev/null
+++ b/modules/sigaction-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-sigaction.c
+
+Depends-on:
+stdbool
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-sigaction
+check_PROGRAMS += test-sigaction
diff --git a/modules/signal b/modules/signal
index c96de90..afe6ab3 100644
--- a/modules/signal
+++ b/modules/signal
@@ -23,8 +23,11 @@ signal.h: signal.in.h
          sed -e 's/@''INCLUDE_NEXT''@/$(INCLUDE_NEXT)/g' \
              -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
              -e 's|@''GNULIB_SIGPROCMASK''@|$(GNULIB_SIGPROCMASK)|g' \
+             -e 's|@''GNULIB_SIGACTION''@|$(GNULIB_SIGACTION)|g' \
              -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)
|g' \
              -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
+             -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
+             -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
              -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
              < $(srcdir)/signal.in.h; \
        } > address@hidden
diff --git a/tests/test-sigaction.c b/tests/test-sigaction.c
new file mode 100644
index 0000000..ad34fd5
--- /dev/null
+++ b/tests/test-sigaction.c
@@ -0,0 +1,88 @@
+/* Test of sigaction() function.
+   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/>.  */
+
+/* Written by Eric Blake <address@hidden>, 2008.  */
+
+#include <config.h>
+
+#include <signal.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);                                                  \
+          signal (SIGABRT, SIG_DFL);                                        \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
+
+#ifndef SA_SIGINFO
+# define SA_SIGINFO 0
+#endif
+
+/* This test is unsafe in the presence of an asynchronous SIGABRT,
+   because we install a signal-handler that is intentionally not
+   async-safe.  Hopefully, this does not lead to too many reports of
+   false failures, since people don't generally use 'kill -s SIGABRT'
+   to end a runaway program.  */
+
+static void
+handler (int sig)
+{
+  static bool second_time;
+  struct sigaction sa;
+  ASSERT (sig == SIGABRT);
+  ASSERT (sigaction (SIGABRT, NULL, &sa) == 0);
+  ASSERT ((sa.sa_flags & SA_SIGINFO) == 0);
+  if (!second_time)
+    {
+      ASSERT ((sa.sa_flags & SA_RESETHAND) == 0);
+      ASSERT (sa.sa_handler == handler);
+      second_time = true;
+    }
+  else
+    ASSERT (sa.sa_handler == SIG_DFL);
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct sigaction sa;
+  struct sigaction old_sa;
+  sa.sa_handler = handler;
+  sa.sa_flags = 0;
+  ASSERT (sigemptyset (&sa.sa_mask) == 0);
+  ASSERT (sigaction (SIGABRT, &sa, NULL) == 0);
+  ASSERT (raise (SIGABRT) == 0);
+  sa.sa_flags = SA_RESETHAND | SA_NODEFER;
+  ASSERT (sigaction (SIGABRT, &sa, &old_sa) == 0);
+  ASSERT (old_sa.sa_flags == 0);
+  ASSERT (old_sa.sa_handler == handler);
+  ASSERT (raise (SIGABRT) == 0);
+  sa.sa_handler = SIG_DFL;
+  ASSERT (sigaction (SIGABRT, &sa, &old_sa) == 0);
+  ASSERT ((old_sa.sa_flags & SA_SIGINFO) == 0);
+  ASSERT (old_sa.sa_handler == SIG_DFL);
+  return 0;
+}
-- 
1.5.5.1


>From 4d335c3018f8c326b4c0ba0e11df9d9a1b188771 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Mon, 16 Jun 2008 16:16:33 -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.
* lib/c-stack.c (SIGACTION_WORKS): Simplify.
(c_stack_action) [!SIGACTION_WORKS]: Use sigaction, not signal.
* lib/fatal-signal.c (uninstall_handlers, install_handlers):
Likewise.
(SA_SIGINFO): Define fallback.
(init_fatal_signals): Assume sigaction.  Don't dereference
sa_handler unless SA_SIGINFO is clear.
* lib/nanosleep.c: Likewise.
(siginterrupt): Delete fallback.
(SA_SIGINFO): Define fallback.
* m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for
siginterrupt.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog            |   17 +++++++++++++++++
 lib/c-stack.c        |   30 ++++++++++++++----------------
 lib/fatal-signal.c   |   21 +++++++++++++++------
 lib/nanosleep.c      |   17 +++++------------
 m4/nanosleep.m4      |    7 +++----
 modules/c-stack      |    1 +
 modules/fatal-signal |    1 +
 modules/nanosleep    |    1 +
 8 files changed, 57 insertions(+), 38 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ad7c04c..49fb34d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2008-06-16  Eric Blake  <address@hidden>
 
+       Use sigaction module rather than signal().
+       * modules/c-stack (Depends-on): Add sigaction.
+       * modules/fatal-signal (Depends-on): Likewise.
+       * modules/nanosleep (Depends-on): Likewise.
+       * lib/c-stack.c (SIGACTION_WORKS): Simplify.
+       (c_stack_action) [!SIGACTION_WORKS]: Use sigaction, not signal.
+       * lib/fatal-signal.c (uninstall_handlers, install_handlers):
+       Likewise.
+       (SA_SIGINFO): Define fallback.
+       (init_fatal_signals): Assume sigaction.  Don't dereference
+       sa_handler unless SA_SIGINFO is clear.
+       * lib/nanosleep.c: Likewise.
+       (siginterrupt): Delete fallback.
+       (SA_SIGINFO): Define fallback.
+       * m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for
+       siginterrupt.
+
        New module sigaction, for mingw.
        * modules/sigaction: New module.
        * m4/sigaction.m4: New file.
diff --git a/lib/c-stack.c b/lib/c-stack.c
index a7ebafa..ebf66d1 100644
--- a/lib/c-stack.c
+++ b/lib/c-stack.c
@@ -83,8 +83,8 @@ 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 (HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined SA_ONSTACK \
+     && defined SA_SIGINFO)
 # define SIGACTION_WORKS 1
 #else
 # define SIGACTION_WORKS 0
@@ -225,6 +225,7 @@ 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;
@@ -236,23 +237,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, 0);
 }
 
 #else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index 5157d7c..85388e5 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -1,5 +1,5 @@
 /* Emergency actions in case of a fatal signal.
-   Copyright (C) 2003-2004, 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2003-2004, 2006-2008 Free Software Foundation, Inc.
    Written by Bruno Haible <address@hidden>, 2003.
 
    This program is free software: you can redistribute it and/or modify
@@ -30,6 +30,9 @@
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 
+#ifndef SA_SIGINFO
+# define SA_SIGINFO 0
+#endif
 
 /* ========================================================================= */
 
@@ -88,7 +91,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,11 +98,10 @@ init_fatal_signals (void)
          struct sigaction action;
 
          if (sigaction (fatal_signals[i], NULL, &action) >= 0
+              && (action.sa_flags & SA_SIGINFO) == 0
              && action.sa_handler == SIG_IGN)
            fatal_signals[i] = -1;
        }
-#endif
-
       fatal_signals_initialized = true;
     }
 }
@@ -132,10 +133,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);
 }
 
 
@@ -175,10 +180,14 @@ static inline void
 install_handlers ()
 {
   size_t i;
+  struct sigaction action;
 
+  action.sa_handler = &fatal_signal_handler;
+  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 456e745..99c71b2 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -1,6 +1,6 @@
 /* Provide a replacement for the POSIX nanosleep function.
 
-   Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007 Free
+   Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008 Free
    Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
@@ -104,8 +104,8 @@ rpl_nanosleep (const struct timespec *requested_delay,
 #  define SIGCONT SIGTERM
 # endif
 
-# if ! HAVE_SIGINTERRUPT
-#  define siginterrupt(sig, flag) /* empty */
+# ifndef SA_SIGINFO
+#  define SA_SIGINFO 0
 # endif
 
 static sig_atomic_t volatile suspended;
@@ -152,22 +152,15 @@ 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 ((oldact.sa_flags & SA_SIGINFO) != 0
+          || oldact.sa_handler != 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/m4/nanosleep.m4 b/m4/nanosleep.m4
index 1d832a3..8780921 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 e87dd1a..d3e7e09 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 4365b3a..8ce9e90 100644
--- a/modules/fatal-signal
+++ b/modules/fatal-signal
@@ -11,6 +11,7 @@ Depends-on:
 xalloc
 stdbool
 unistd
+sigaction
 sigprocmask
 
 configure.ac:
diff --git a/modules/nanosleep b/modules/nanosleep
index 3035a13..55075ae 100644
--- a/modules/nanosleep
+++ b/modules/nanosleep
@@ -9,6 +9,7 @@ Depends-on:
 clock-time
 extensions
 gettime
+sigaction
 stdbool
 sys_time
 time
-- 
1.5.5.1







reply via email to

[Prev in Thread] Current Thread [Next in Thread]