New module 'sigprocmask'.
authorBruno Haible <bruno@clisp.org>
Mon, 16 Oct 2006 11:55:35 +0000 (11:55 +0000)
committerBruno Haible <bruno@clisp.org>
Mon, 16 Oct 2006 11:55:35 +0000 (11:55 +0000)
ChangeLog
MODULES.html.sh
lib/fatal-signal.c
lib/sigprocmask.c [new file with mode: 0644]
lib/sigprocmask.h [new file with mode: 0644]
m4/fatal-signal.m4
m4/signalblocking.m4
modules/fatal-signal
modules/sigprocmask [new file with mode: 0644]

index 5d46d88..8393e8c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2006-10-14  Bruno Haible  <bruno@clisp.org>
+
+       * modules/sigprocmask: New file.
+       * lib/sigprocmask.h: New file.
+       * lib/sigprocmask.c: New file.
+       * m4/signalblocking.m4 (gl_SIGNALBLOCKING): Renamed from
+       gt_SIGNALBLOCKING. When not defining HAVE_POSIX_SIGNALBLOCKING,
+       request sigprocmask.o.
+       (gl_PREREQ_SIGPROCMASK): New macro.
+       * modules/fatal-signal (Files): Remove m4/signalblocking.m4.
+       (Depends-on): Add sigprocmask.
+       * m4/fatal-signal.m4 (gl_FATAL_SIGNAL): Don't require
+       gt_SIGNALBLOCKING. Test for 'raise' only once.
+       * lib/fatal-signal.c: Include sigprocmask.h.
+       (fatal_signal_set, init_fatal_signal_set, block_fatal_signals,
+       unblock_fatal_signals): Define always.
+       * MODULES.html.sh (Support for systems lacking POSIX:2001): Add
+       sigprocmask.
+
 2006-10-14  Paul Eggert  <eggert@cs.ucla.edu>
 
        Sync from Automake.
index 17e7244..1196121 100755 (executable)
@@ -1849,6 +1849,7 @@ func_all_modules ()
   func_module regex
   func_module rename
   func_module rmdir
+  func_module sigprocmask
   func_module ssize_t
   func_module strtok_r
   func_module sys_stat
index 8a3a99c..f85b60f 100644 (file)
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <unistd.h>
 
+#include "sigprocmask.h"
 #include "xalloc.h"
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
@@ -231,8 +232,6 @@ at_fatal_signal (action_t action)
 /* ========================================================================= */
 
 
-#if HAVE_POSIX_SIGNALBLOCKING
-
 static sigset_t fatal_signal_set;
 
 static void
@@ -269,20 +268,3 @@ unblock_fatal_signals ()
   init_fatal_signal_set ();
   sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 }
-
-#else
-
-/* Don't bother caring about the old systems which don't have POSIX signal
-   blocking.  */
-
-void
-block_fatal_signals ()
-{
-}
-
-void
-unblock_fatal_signals ()
-{
-}
-
-#endif
diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c
new file mode 100644 (file)
index 0000000..149d270
--- /dev/null
@@ -0,0 +1,192 @@
+/* POSIX compatible signal blocking.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "sigprocmask.h"
+
+#include <errno.h>
+#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.  */
+
+/* A signal handler.  */
+typedef void (*handler_t) (int signal);
+
+int
+sigismember (const sigset_t *set, int sig)
+{
+  if (sig >= 0 && sig < NSIG)
+    return (*set >> sig) & 1;
+  else
+    return 0;
+}
+
+int
+sigemptyset (sigset_t *set)
+{
+  *set = 0;
+  return 0;
+}
+
+int
+sigaddset (sigset_t *set, int sig)
+{
+  if (sig >= 0 && sig < NSIG)
+    {
+      *set |= 1U << sig;
+      return 0;
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+}
+
+int
+sigdelset (sigset_t *set, int sig)
+{
+  if (sig >= 0 && sig < NSIG)
+    {
+      *set &= ~(1U << sig);
+      return 0;
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+}
+
+int
+sigfillset (sigset_t *set)
+{
+  *set = (2U << (NSIG - 1)) - 1;
+  return 0;
+}
+
+/* Set of currently blocked signals.  */
+static sigset_t blocked_set /* = 0 */;
+
+/* Set of currently blocked and pending signals.  */
+static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */;
+
+/* Signal handler that is installed for blocked signals.  */
+static void
+blocked_handler (int sig)
+{
+  if (sig >= 0 && sig < NSIG)
+    pending_array[sig] = 1;
+}
+
+int
+sigpending (sigset_t *set)
+{
+  sigset_t pending = 0;
+  int sig;
+
+  for (sig = 0; sig < NSIG; sig++)
+    if (pending_array[sig])
+      pending |= 1U << sig;
+  return pending;
+}
+
+/* The previous signal handlers.
+   Only the array elements corresponding to blocked signals are relevant.  */
+static handler_t old_handlers[NSIG];
+
+int
+sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
+{
+  if (old_set != NULL)
+    *old_set = blocked_set;
+
+  if (set != NULL)
+    {
+      sigset_t new_blocked_set;
+      sigset_t to_unblock;
+      sigset_t to_block;
+
+      switch (operation)
+       {
+       case SIG_BLOCK:
+         new_blocked_set = blocked_set | *set;
+         break;
+       case SIG_SETMASK:
+         new_blocked_set = *set;
+         break;
+       case SIG_UNBLOCK:
+         new_blocked_set = blocked_set & ~*set;
+         break;
+       default:
+         errno = EINVAL;
+         return -1;
+       }
+      to_unblock = blocked_set & ~new_blocked_set;
+      to_block = new_blocked_set & ~blocked_set;
+
+      if (to_block != 0)
+       {
+         int sig;
+
+         for (sig = 0; sig < NSIG; sig++)
+           if ((to_block >> sig) & 1)
+             {
+               pending_array[sig] = 0;
+               if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR)
+                 blocked_set |= 1U << sig;
+             }
+       }
+
+      if (to_unblock != 0)
+       {
+         sig_atomic_t received[NSIG];
+         int sig;
+
+         for (sig = 0; sig < NSIG; sig++)
+           if ((to_unblock >> sig) & 1)
+             {
+               if (signal (sig, old_handlers[sig]) != blocked_handler)
+                 /* The application changed a signal handler while the signal
+                    was blocked.  We don't support this.  */
+                 abort ();
+               received[sig] = pending_array[sig];
+               blocked_set &= ~(1U << sig);
+               pending_array[sig] = 0;
+             }
+           else
+             received[sig] = 0;
+
+         for (sig = 0; sig < NSIG; sig++)
+           if (received[NSIG])
+             {
+               #if HAVE_RAISE
+               raise (sig);
+               #else
+               kill (getpid (), sig);
+               #endif
+             }
+       }
+    }
+  return 0;
+}
diff --git a/lib/sigprocmask.h b/lib/sigprocmask.h
new file mode 100644 (file)
index 0000000..f88351f
--- /dev/null
@@ -0,0 +1,64 @@
+/* POSIX compatible signal blocking.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <signal.h>
+
+#if ! HAVE_POSIX_SIGNALBLOCKING
+
+# include "verify.h"
+
+/* Maximum signal number + 1.  */
+# ifndef NSIG
+#  define NSIG 32
+# endif
+
+/* This code supports only 32 signals.  */
+verify (NSIG <= 32);
+
+/* A set or mask of signals.  */
+typedef unsigned int sigset_t;
+
+/* Test whether a given signal is contained in a signal set.  */
+extern int sigismember (const sigset_t *set, int sig);
+
+/* Initialize a signal set to the empty set.  */
+extern int sigemptyset (sigset_t *set);
+
+/* Add a signal to a signal set.  */
+extern int sigaddset (sigset_t *set, int sig);
+
+/* Remove a signal from a signal set.  */
+extern int sigdelset (sigset_t *set, int sig);
+
+/* Fill a signal set with all possible signals.  */
+extern int sigfillset (sigset_t *set);
+
+/* Return the set of those blocked signals that are pending.  */
+extern int sigpending (sigset_t *set);
+
+/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET.
+   Then, if SET is not NULL, affect the current set of blocked signals by
+   combining it with *SET as indicated in OPERATION.
+   In this implementation, you are not allowed to change a signal handler
+   while the signal is blocked.  */
+# define SIG_BLOCK   0  /* blocked_set = blocked_set | *set; */
+# define SIG_SETMASK 1  /* blocked_set = *set; */
+# define SIG_UNBLOCK 2  /* blocked_set = blocked_set & ~*set; */
+extern int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set);
+
+#endif
index 062f6e0..c188b14 100644 (file)
@@ -1,13 +1,13 @@
-# fatal-signal.m4 serial 3
-dnl Copyright (C) 2003-2004 Free Software Foundation, Inc.
+# fatal-signal.m4 serial 4
+dnl Copyright (C) 2003-2004, 2006 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.
 
 AC_DEFUN([gl_FATAL_SIGNAL],
 [
-  AC_REQUIRE([gt_SIGNALBLOCKING])
   AC_REQUIRE([gt_TYPE_SIG_ATOMIC_T])
   AC_CHECK_HEADERS_ONCE(unistd.h)
-  AC_CHECK_FUNCS(raise sigaction)
+  AC_CHECK_FUNCS_ONCE(raise)
+  AC_CHECK_FUNCS(sigaction)
 ])
index fe91f29..bb120f5 100644 (file)
@@ -1,5 +1,5 @@
-# signalblocking.m4 serial 1 (gettext-0.11)
-dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+# signalblocking.m4 serial 2 (gettext-0.15.1)
+dnl Copyright (C) 2001-2002, 2006 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.
@@ -9,13 +9,23 @@ dnl with or without modifications, as long as this notice is preserved.
 # 2) SYSV: sighold, sigrelse
 # 3) BSD: sigblock, sigsetmask
 # For simplicity, here we check only for the POSIX signal blocking.
-AC_DEFUN([gt_SIGNALBLOCKING],
+AC_DEFUN([gl_SIGNALBLOCKING],
 [
   signals_not_posix=
   AC_EGREP_HEADER(sigset_t, signal.h, , signals_not_posix=1)
   if test -z "$signals_not_posix"; then
-    AC_CHECK_FUNC(sigprocmask,
-      AC_DEFINE(HAVE_POSIX_SIGNALBLOCKING, 1,
-       [Define to 1 if you have the sigset_t type and the sigprocmask function.]))
+    AC_CHECK_FUNC(sigprocmask, [gl_cv_func_sigprocmask=1])
   fi
+  if test -n "$gl_cv_func_sigprocmask"; then
+    AC_DEFINE([HAVE_POSIX_SIGNALBLOCKING], 1,
+      [Define to 1 if you have the sigset_t type and the sigprocmask function.])
+  else
+    AC_LIBOBJ([sigprocmask])
+    gl_PREREQ_SIGPROCMASK
+  fi
+])
+
+# Prerequisites of lib/sigprocmask.c.
+AC_DEFUN([gl_PREREQ_SIGPROCMASK], [
+  AC_CHECK_FUNCS_ONCE(raise)
 ])
index dce33bd..4365b3a 100644 (file)
@@ -5,13 +5,13 @@ Files:
 lib/fatal-signal.h
 lib/fatal-signal.c
 m4/fatal-signal.m4
-m4/signalblocking.m4
 m4/sig_atomic_t.m4
 
 Depends-on:
 xalloc
 stdbool
 unistd
+sigprocmask
 
 configure.ac:
 gl_FATAL_SIGNAL
diff --git a/modules/sigprocmask b/modules/sigprocmask
new file mode 100644 (file)
index 0000000..314e4be
--- /dev/null
@@ -0,0 +1,26 @@
+Description:
+POSIX compatible signal blocking.
+
+Files:
+lib/sigprocmask.h
+lib/sigprocmask.c
+m4/signalblocking.m4
+
+Depends-on:
+verify
+stdint
+
+configure.ac:
+gl_SIGNALBLOCKING
+
+Makefile.am:
+
+Include:
+"sigprocmask.h"
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
+