bug-gnulib
[Top][All Lists]
Advanced

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

Re: sigaction, SA_SIGINFO, and SIG_IGN


From: Eric Blake
Subject: Re: sigaction, SA_SIGINFO, and SIG_IGN
Date: Sat, 21 Jun 2008 16:31:41 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080421 Thunderbird/2.0.0.14 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Bruno Haible on 6/20/2008 6:12 PM:
|>   if (sigaction (fatal_signals[i], NULL, &action) == 0
|>       && get_handler (&action) == SIG_IGN)
|>     fatal_signals[i] = -1;
|
| This is acceptable to me. You are free to add this to lib/fatal-signal.c
| (marking the function as "static inline", please).
|
| Erik Blake wrote:
|> Perhaps it would be nicer if the prelude were part of
|> signal.in.h, so that both modules could use it?
|
| Better use a private include file for it. signal.in.h is supposed to be
| only the replacement for the POSIX/glibc <signal.h>. The fact that it's
| used unconditionally by modules/signal is only a missed optimization.

Done as follows, as part of committing sigaction.  It turns out that since
mingw lacks struct sigaction, this only makes sense when using
sigaction().  I named the helper file sig-handler.h.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkhdgU0ACgkQ84KuGfSFAYBOyACfSEp6R9fuG9nrP4A3KmboRjQ9
c/oAoIXF/R82OqfcwGaDjmfbJvztUCtj
=hXJU
-----END PGP SIGNATURE-----
>From 6dbadedb84d0fe02292a39f22942b8c172487ebf Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Sat, 21 Jun 2008 07:06:28 -0600
Subject: [PATCH] Improve robustness of sigprocmask by overriding signal.

* lib/signal.in.h (rpl_signal): Override signal when sigprocmask
is in use.
* lib/sigprocmask.c (blocked_handler): Reinstall block handler.
(SIGKILL, SIGSTOP): Provide fallbacks.
(rpl_signal): Implement.
(old_handlers, blocked_set): Mark volatile, since sigprocmask and
signal can be called inside handlers.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog         |    9 +++++++
 lib/signal.in.h   |   14 ++++++++---
 lib/sigprocmask.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9f4d999..7d08ae6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2008-06-21  Eric Blake  <address@hidden>
 
+       Improve robustness of sigprocmask by overriding signal.
+       * lib/signal.in.h (rpl_signal): Override signal when sigprocmask
+       is in use.
+       * lib/sigprocmask.c (blocked_handler): Reinstall block handler.
+       (SIGKILL, SIGSTOP): Provide fallbacks.
+       (rpl_signal): Implement.
+       (old_handlers, blocked_set): Mark volatile, since sigprocmask and
+       signal can be called inside handlers.
+
        Fix nanosleep module on mingw.
        * modules/nanosleep (Depends-on): Add sys_select.
        * lib/nanosleep.c (HAVE_SYS_SELECT_H): Rely on gnulib module.
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 9f82ba7..eb16afb 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
@@ -33,6 +33,10 @@
 
 /* The definition of GL_LINK_WARNING is copied here.  */
 
+/* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.  */
+#if address@hidden@
+# include <sys/types.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -41,9 +45,6 @@ extern "C" {
 
 #if address@hidden@
 
-/* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.  */
-# include <sys/types.h>
-
 /* Maximum signal number + 1.  */
 # ifndef NSIG
 #  define NSIG 32
@@ -85,6 +86,11 @@ 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);
 
+# define signal rpl_signal
+/* Install the handler FUNC for signal SIG, and return the previous
+   handler.  */
+extern void (*signal (int sig, void (*func) (int))) (int);
+
 #endif
 
 
diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c
index 456545a..87d585c 100644
--- a/lib/sigprocmask.c
+++ b/lib/sigprocmask.c
@@ -24,9 +24,24 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-/* We assume that a platform without POSIX signal blocking functions also
-   does not have the POSIX sigaction() function, only the signal() function.
-   This is true for Woe32 platforms.  */
+/* 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,
+   where any handler is uninstalled prior to being invoked.  This is
+   true for Woe32 platforms.  */
+
+/* We use raw signal(), but also provide a wrapper rpl_signal() so
+   that applications can query or change a blocked signal.  */
+#undef signal
+
+/* Provide invalid signal numbers as fallbacks if the uncatchable
+   signals are not defined.  */
+#ifndef SIGKILL
+# define SIGKILL (-1)
+#endif
+#ifndef SIGSTOP
+# define SIGSTOP (-1)
+#endif
 
 /* A signal handler.  */
 typedef void (*handler_t) (int signal);
@@ -85,7 +100,7 @@ sigfillset (sigset_t *set)
 }
 
 /* Set of currently blocked signals.  */
-static sigset_t blocked_set /* = 0 */;
+static volatile sigset_t blocked_set /* = 0 */;
 
 /* Set of currently blocked and pending signals.  */
 static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */;
@@ -94,6 +109,12 @@ static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } 
*/;
 static void
 blocked_handler (int sig)
 {
+  /* Reinstall the handler, in case the signal occurs multiple times
+     while blocked.  There is an inherent race where an asynchronous
+     signal in between when the kernel uninstalled the handler and
+     when we reinstall it will trigger the default handler; oh
+     well.  */
+  signal (sig, blocked_handler);
   if (sig >= 0 && sig < NSIG)
     pending_array[sig] = 1;
 }
@@ -113,7 +134,7 @@ sigpending (sigset_t *set)
 
 /* The previous signal handlers.
    Only the array elements corresponding to blocked signals are relevant.  */
-static handler_t old_handlers[NSIG];
+static volatile handler_t old_handlers[NSIG];
 
 int
 sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
@@ -184,3 +205,37 @@ sigprocmask (int operation, const sigset_t *set, sigset_t 
*old_set)
     }
   return 0;
 }
+
+/* Install the handler FUNC for signal SIG, and return the previous
+   handler.  */
+handler_t
+rpl_signal (int sig, 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.  */
+  if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP
+      && handler != SIG_ERR)
+    {
+      if (blocked_set & (1U << sig))
+       {
+         /* POSIX states that sigprocmask and signal are both
+            async-signal-safe.  This is not true of our
+            implementation - there is a slight data race where an
+            asynchronous interrupt on signal A can occur after we
+            install blocked_handler but before we have updated
+            old_handlers for signal B, such that handler A can see
+            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];
+         old_handlers[sig] = handler;
+         return result;
+       }
+      return signal (sig, handler);
+    }
+  else
+    {
+      errno = EINVAL;
+      return SIG_ERR;
+    }
+}
-- 
1.5.6


>From cfb3906f210bec09f48f5d48511b72064153311a Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Sat, 21 Jun 2008 14:32:55 -0600
Subject: [PATCH] New module sigaction, for mingw.

* modules/sigaction: New module...
* modules/sigaction-tests: ...and its test.
* m4/sigaction.m4: New file.
* lib/sigaction.c: Likewise.
* tests/test-sigaction.c: Likewise.
* m4/signal_h.m4 (gl_SIGNAL_H_DEFAULTS): Add sigaction variables.
* modules/signal (Makefile.am): Likewise.
* lib/signal.in.h (address@hidden@): Define replacements when
needed.
* 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                             |   19 ++++
 MODULES.html.sh                       |    1 +
 doc/posix-functions/sigaction.texi    |   25 ++++-
 doc/posix-functions/siginterrupt.texi |    3 +
 doc/posix-headers/signal.texi         |   14 +++-
 lib/sigaction.c                       |  187 +++++++++++++++++++++++++++++++++
 lib/signal.in.h                       |   62 ++++++++++-
 m4/sigaction.m4                       |   35 ++++++
 m4/signal_h.m4                        |    7 +-
 modules/sigaction                     |   25 +++++
 modules/sigaction-tests               |   10 ++
 modules/signal                        |    3 +
 tests/test-sigaction.c                |   97 +++++++++++++++++
 13 files changed, 479 insertions(+), 9 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 7d08ae6..e3b0279 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2008-06-21  Eric Blake  <address@hidden>
 
+       New module sigaction, for mingw.
+       * modules/sigaction: New module...
+       * modules/sigaction-tests: ...and its test.
+       * m4/sigaction.m4: New file.
+       * lib/sigaction.c: Likewise.
+       * tests/test-sigaction.c: Likewise.
+       * m4/signal_h.m4 (gl_SIGNAL_H_DEFAULTS): Add sigaction variables.
+       * modules/signal (Makefile.am): Likewise.
+       * lib/signal.in.h (address@hidden@): Define replacements when
+       needed.
+       * 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.
+
        Improve robustness of sigprocmask by overriding signal.
        * lib/signal.in.h (rpl_signal): Override signal when sigprocmask
        is in use.
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..56795d9 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, Interix 3.5.
+
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..68ac3c5 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..cb4f580 100644
--- a/doc/posix-headers/signal.texi
+++ b/doc/posix-headers/signal.texi
@@ -3,12 +3,24 @@
 
 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:
 @itemize
address@hidden
address@hidden sigaction} lacks the @code{sa_sigaction} member on some
+platforms; this can also be detected by whether @code{SA_SIGINFO} is defined:
+Interix 3.5.
 @end itemize
diff --git a/lib/sigaction.c b/lib/sigaction.c
new file mode 100644
index 0000000..9b0c92f
--- /dev/null
+++ b/lib/sigaction.c
@@ -0,0 +1,187 @@
+/* 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>
+
+/* This implementation of sigaction is tailored to Woe32 behavior:
+   signal() has SysV semantics (ie. the handler is uninstalled before
+   it is invoked).  This is an inherent data race if an asynchronous
+   signal is sent twice in a row before we can reinstall our handler,
+   but there's nothing we can do about it.  Meanwhile, sigprocmask()
+   is not present, and while we can use the gnulib replacement to
+   provide critical sections, it too suffers from potential data races
+   in the face of an ill-timed asynchronous signal.  And we compound
+   the situation by reading static storage in a signal handler, which
+   POSIX warns is not generically async-signal-safe.  Oh well.
+
+   Additionally, SIGCHLD is not defined, so we don't implement
+   SA_NOCLDSTOP or SA_NOCLDWAIT; sigaltstack() is not present, so we
+   don't implement SA_ONSTACK; and siginterrupt() is not present, so
+   we don't implement SA_RESTART.  Supporting SA_SIGINFO is impossible
+   to do portably.
+
+   POSIX states that an application should not mix signal() and
+   sigaction().  We support the use of signal() within the gnulib
+   sigprocmask() substitute, but all other application code linked
+   with this module should stick with only sigaction().  */
+
+/* Check some of our assumptions.  */
+#if defined SIGCHLD || defined HAVE_SIGALTSTACK || defined HAVE_SIGINTERRUPT
+# error "Revisit the assumptions made in the sigaction module"
+#endif
+
+/* Out-of-range substitutes make a good fallback for uncatchable
+   signals.  */
+#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.  If sa_handler for an entry is NULL, then
+   that signal is not currently handled by the sigaction handler.  */
+static struct sigaction volatile action_array[NSIG] /* = 0 */;
+
+/* Signal handler that is installed for signals.  */
+static void
+sigaction_handler (int sig)
+{
+  handler_t handler;
+  sigset_t mask;
+  sigset_t oldmask;
+  int saved_errno = errno;
+  if (sig < 0 || NSIG <= sig || !action_array[sig].sa_handler)
+    {
+      /* Unexpected situation; be careful to avoid recursive abort.  */
+      if (sig == SIGABRT)
+       signal (SIGABRT, SIG_DFL);
+      abort ();
+    }
+
+  /* Reinstall the signal handler when required; otherwise update the
+     bookkeeping so that the user's handler may call sigaction and get
+     accurate results.  We know the signal isn't currently blocked, or
+     we wouldn't be in its handler, therefore we know that we are not
+     interrupting a sigaction() call.  There is a race where any
+     asynchronous instance of the same signal occurring before we
+     reinstall the handler will trigger the default handler; oh
+     well.  */
+  handler = 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.  */
+  errno = saved_errno;
+  handler (sig);
+  saved_errno = errno;
+  sigprocmask (SIG_SETMASK, &oldmask, NULL);
+  errno = saved_errno;
+}
+
+/* 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)
+{
+  sigset_t mask;
+  sigset_t oldmask;
+  int saved_errno;
+
+  if (sig < 0 || NSIG <= sig || sig == SIGKILL || sig == SIGSTOP
+      || (act && act->sa_handler == SIG_ERR))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* POSIX requires sigaction() to be async-signal-safe.  In other
+     words, if an asynchronous signal can occur while we are anywhere
+     inside this function, the user's handler could then call
+     sigaction() recursively and expect consistent results.  We meet
+     this rule by using sigprocmask to block all signals before
+     modifying any data structure that could be read from a signal
+     handler; this works since we know that the gnulib sigprocmask
+     replacement does not try to use sigaction() from its handler.  */
+  if (!act && !oact)
+    return 0;
+  sigfillset (&mask);
+  sigprocmask (SIG_BLOCK, &mask, &oldmask);
+  if (oact)
+    {
+      if (action_array[sig].sa_handler)
+        *oact = action_array[sig];
+      else
+        {
+          /* Safe to change the handler at will here, since all
+             signals are currently blocked.  */
+          oact->sa_handler = signal (sig, SIG_DFL);
+          if (oact->sa_handler == SIG_ERR)
+            goto failure;
+          signal (sig, oact->sa_handler);
+          oact->sa_flags = SA_RESETHAND | SA_NODEFER;
+          sigemptyset (&oact->sa_mask);
+        }
+    }
+
+  if (act)
+    {
+      /* Safe to install the handler before updating action_array,
+         since all signals are currently blocked.  */
+      if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN)
+        {
+          if (signal (sig, act->sa_handler) == SIG_ERR)
+            goto failure;
+          action_array[sig].sa_handler = NULL;
+        }
+      else
+        {
+          if (signal (sig, sigaction_handler) == SIG_ERR)
+            goto failure;
+          action_array[sig] = *act;
+        }
+    }
+  sigprocmask (SIG_SETMASK, &oldmask, NULL);
+  return 0;
+
+ failure:
+  saved_errno = errno;
+  sigprocmask (SIG_SETMASK, &oldmask, NULL);
+  errno = saved_errno;
+  return -1;
+}
diff --git a/lib/signal.in.h b/lib/signal.in.h
index eb16afb..30fa929 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -34,9 +34,7 @@
 /* The definition of GL_LINK_WARNING is copied here.  */
 
 /* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.  */
-#if address@hidden@
-# include <sys/types.h>
-#endif
+#include <sys/types.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -91,7 +89,63 @@ extern int sigprocmask (int operation, const sigset_t *set, 
sigset_t *old_set);
    handler.  */
 extern void (*signal (int sig, void (*func) (int))) (int);
 
-#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;
+};
+
+/* Present to allow compilation, but unsupported by gnulib.  */
+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.  POSIX
+       says that implementations may, but not must, make sa_sigaction
+       overlap with sa_handler, but we know of no implementation where
+       they do not overlap.  */
+    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..2f1a4cd
--- /dev/null
+++ b/m4/sigaction.m4
@@ -0,0 +1,35 @@
+# 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_FUNCS_ONCE([sigaltstack siginterrupt])
+  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..5084e9e
--- /dev/null
+++ b/modules/sigaction-tests
@@ -0,0 +1,10 @@
+Files:
+tests/test-sigaction.c
+
+Depends-on:
+
+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..81abe89
--- /dev/null
+++ b/tests/test-sigaction.c
@@ -0,0 +1,97 @@
+/* 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 <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 int entry_count;
+  struct sigaction sa;
+  ASSERT (sig == SIGABRT);
+  ASSERT (sigaction (SIGABRT, NULL, &sa) == 0);
+  ASSERT ((sa.sa_flags & SA_SIGINFO) == 0);
+  switch (entry_count++)
+    {
+    case 0:
+      ASSERT ((sa.sa_flags & SA_RESETHAND) == 0);
+      ASSERT (sa.sa_handler == handler);
+      break;
+    case 1:
+      ASSERT (sa.sa_handler == SIG_DFL);
+      break;
+    default:
+      ASSERT (0);
+    }
+}
+
+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);
+  sa.sa_handler = SIG_IGN;
+  ASSERT (sigaction (SIGABRT, &sa, NULL) == 0);
+  ASSERT (raise (SIGABRT) == 0);
+  ASSERT (sigaction (SIGABRT, NULL, &old_sa) == 0);
+  ASSERT (old_sa.sa_handler == SIG_IGN);
+  ASSERT (raise (SIGABRT) == 0);
+  return 0;
+}
-- 
1.5.6


>From 4b2f21b36a615728ebf2a0e1bc2c8def175703a8 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
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 <address@hidden>
---
 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 e3b0279..dcb8f5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2008-06-21  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.
+       * 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 ff892c5..96bd2bf 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 7654d1f..eca46db 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -26,11 +26,11 @@
 #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);
 }
 
 
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
index 1239cb0..1732c59 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -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
index 0000000..969f679
--- /dev/null
+++ b/lib/sig-handler.h
@@ -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 */
diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c
index 87d585c..a8f2eb4 100644
--- a/lib/sigprocmask.c
+++ b/lib/sigprocmask.c
@@ -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;
        }
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 8e8eb8a..296fbd3 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 3ff486e..61b4527 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 60c0e8c..8490573 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 e093112..37adc63 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:
-- 
1.5.6


reply via email to

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