bug-gnulib
[Top][All Lists]
Advanced

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

Re: RFC: sigaction module


From: Eric Blake
Subject: Re: RFC: sigaction module
Date: Fri, 20 Jun 2008 21:58:43 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Bruno Haible <bruno <at> clisp.org> writes:

> > 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.
> 
> That's fully sufficient. Nice work!

Your review hopefully made it even better.

> 
> > 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
> 
> Remember that there are at least two async signals: Ctrl-C leading to SIGINT,
> and also Ctrl-Break leading to SIGBREAK.

OK, the version of the patch posted below should be safer in the presence of 
async signals (it will never be perfect, due to mingw's inherent data race 
caused by the temporary uninstallation of a handler, as well as its inability 
to atomically block signals).
> 
> > mingw lacks sigprocmask.  There is a gnulib module replacement, but it too
> > suffers from the race condition.
> 
> The sigprocmask replacement may, when a signal arrives just after it has
> been unblocked, still execute the handler for this signal. This is more
> benign than the race condition that you introduce here: When a signal
> arrives between the
>    signal (sig, SIG_DFL)
> and
>    signal (sig, sigaction_handler)
> lines, the signal will undergo default handling. Executing either the old
> or the new handler would be excusable, but not an open race like this.

The open race no longer exists; the probe for an existing handler is now 
covered when all signals are blocked, so if the signal arrives during that 
time, the sigprocmask module schedules the interrupt to re-fire, then the 
sigaction module restores the signal back to the correct state before 
unblocking signals.

> 
> > +Posix recommends using @code{sigaction} with SA_NODEFER instead.
> 
> s/Posix/POSIX/, no?

For consistency with the rest of doc/posix-*/*.texi, I went with POSIX.

> 
> > +/* We assume that a platform without POSIX sigaction implements SysV
> > +   semantics in signal() (ie. the handler is uninstalled before it is
> > +   invoked).
> 
> Yes, this is how msvcrt behaves.

I reworded the comments to be more direct.

> 
> > +static struct sigaction action_array[NSIG] /* = 0 */;
> 
> This array needs to be marked volatile, because you access it from a
> signal handler. (You must forbid the compiler to reorder statements in
> the sigaction() function in a non-obvious way.)

Done.

> If you need to access the action_array from within the handler, you need to
> change the statements
> 
>           if (signal (sig, sigaction_handler) == SIG_ERR)
>             return -1;
>           /* Consider what happens if a signal arrives ---HERE--- */
>           action_array[sig] = *act;
> 
> to
> 
>           action_array[sig] = *act;
>           if (signal (sig, sigaction_handler) == SIG_ERR)
>             return -1;

No longer necessary - the fix to sigprocmask to allow changing a blocked signal 
means that we no longer access the array from sigaction_handler until after we 
unblock signals, thus the array is stable by then.

> 
> > +    {
> > +      /* Unexpected situation; be careful to avoid recursive abort.  */
> > +      if (sig == SIGABRT)
> > +        exit (1);
> > +      abort ();
> 
> I don't like exit(1) here, because it leaves no clue where to look when it
> really occurs. Why not like this:
> 
>          if (sig == SIGABRT)
>            signal (sig, SIG_DFL);
>          abort ();

Done.

> 
> Like Paul, I would like to see atomicity here. Can you merge the two signal()
> calls, to guarantee atomicity of the change?

Three signal() calls, in the case of act and oact both non-NULL.  But again, 
with the sigprocmask improvement, this is now an atomic change from the 
perspective of signal handling.

> 
> > +          action_array[sig] = *act;
> 
> This statement is not atomic, because action_array[sig] consists of
> several memory words. Yet you access all three words from the signal handler.
> What happens if a signal occurs right in the middle of this copying operation?

Can't happen, now that sigprocmask has the signal blocked during the copy 
operation.

> 
> > +# 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;
> > +};
> 
> I think this requires a #include <sys/types.h>.

Done.  I assume blindly including <sys/types.h> is okay, even though POSIX 
doesn't mention that <signal.h> might make visible the symbols in 
<sys/types.h>, since enough other headers end up using <sys/types.h> anyway.

This series includes a resend of my 'sigprocmask improvement' thread; it really 
does make sigaction easier to write.

Any last nits before I apply?


>From 48e200871b11a0569b3760f5b99f8a6a7c0c1de8 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 20 Jun 2008 07:27:08 -0600
Subject: [PATCH] Improve robustness of sigprocmask by overriding signal.

* lib/signal.in.h (includes): Hoist <sys/types.h> outside of
extern "C" block.
(rpl_signal): Override signal when sigprocmask is in use.
* lib/sigprocmask.c (blocked_handler): Reinstall block handler.
(SIGKILL, SIGSTOP): Provide fallbacks.
(rpl_signal): Implement.

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

diff --git a/ChangeLog b/ChangeLog
index bdb444a..8b71ccc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-06-20  Eric Blake  <address@hidden>
+
+       Improve robustness of sigprocmask by overriding signal.
+       * lib/signal.in.h (includes): Hoist <sys/types.h> outside of
+       extern "C" block.
+       (rpl_signal): Override signal when sigprocmask is in use.
+       * lib/sigprocmask.c (blocked_handler): Reinstall block handler.
+       (SIGKILL, SIGSTOP): Provide fallbacks.
+       (rpl_signal): Implement.
+
 2008-06-19  Bruno Haible  <address@hidden>
 
        Fix CVS-ism.
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..a895631 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);
@@ -94,6 +109,12 @@ static volatile sig_atomic_t pending_array[NSIG]
 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;
 }
@@ -184,3 +205,37 @@ sigprocmask (int operation, const sigset_t *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 bf9ea16edeac27d70bb3d8ba4822eda128ed8180 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 19 Jun 2008 19:55:42 -0600
Subject: [PATCH] New module sigaction, for mingw.

* modules/sigaction: New module...
* modules/sigaction-tests: ...and its test.
* modules/raise (License): Relicense as LGPL.
* 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.
---
 ChangeLog                             |   20 ++++
 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/raise                         |    3 +-
 modules/sigaction                     |   25 +++++
 modules/sigaction-tests               |   10 ++
 modules/signal                        |    3 +
 tests/test-sigaction.c                |   97 +++++++++++++++++
 14 files changed, 481 insertions(+), 11 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 8b71ccc..3bcead8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2008-06-20  Eric Blake  <address@hidden>
 
+       New module sigaction, for mingw.
+       * modules/sigaction: New module...
+       * modules/sigaction-tests: ...and its test.
+       * modules/raise (License): Relicense as LGPL.
+       * 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 (includes): Hoist <sys/types.h> outside of
        extern "C" block.
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
    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/raise b/modules/raise
index a303e29..ef2c758 100644
--- a/modules/raise
+++ b/modules/raise
@@ -14,8 +14,7 @@ Makefile.am:
 Include:
 
 License:
-GPL
+LGPL
 
 Maintainer:
 Jim Meyering
-
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 8140f1227f630f3b54af964c834f9f8356df871a Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 20 Jun 2008 08:25:11 -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 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.
* m4/nanosleep.m4 (gl_PREREQ_NANOSLEEP): Drop check for
siginterrupt.
---
 ChangeLog            |   13 +++++++++++++
 lib/c-stack.c        |   33 +++++++++++++++------------------
 lib/fatal-signal.c   |   23 +++++++++++++++--------
 lib/nanosleep.c      |   18 +++++-------------
 m4/nanosleep.m4      |    7 +++----
 modules/c-stack      |    1 +
 modules/fatal-signal |    1 +
 modules/nanosleep    |    1 +
 8 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3bcead8..97e1626 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2008-06-20  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 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.
+       * 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..f4ba782 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -30,7 +30,6 @@
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 
-
 /* ========================================================================= */
 
 
@@ -88,7 +87,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++)
@@ -103,7 +101,6 @@ init_fatal_signals (void)
              && action.sa_handler == SIG_IGN)
            fatal_signals[i] = -1;
        }
-#endif
 
       fatal_signals_initialized = true;
     }
@@ -136,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);
 }
 
 
@@ -162,9 +163,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 +176,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 456e745..60c5de8 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,10 +104,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. */
@@ -152,22 +148,18 @@ 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);
+      /* 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.  */
       if (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 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 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.6







reply via email to

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