summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2006-10-16 11:55:35 +0000
committerBruno Haible <bruno@clisp.org>2006-10-16 11:55:35 +0000
commitfa9f85a436cb8239695046be4feb68211fe71af1 (patch)
tree32c21b4645b295be15abcde653db45ff57ce9b27
parentd9456582d69319f14af18102ab7e97bb5feec06e (diff)
downloadgnulib-fa9f85a436cb8239695046be4feb68211fe71af1.tar.gz
New module 'sigprocmask'.
-rw-r--r--ChangeLog19
-rwxr-xr-xMODULES.html.sh1
-rw-r--r--lib/fatal-signal.c20
-rw-r--r--lib/sigprocmask.c192
-rw-r--r--lib/sigprocmask.h64
-rw-r--r--m4/fatal-signal.m48
-rw-r--r--m4/signalblocking.m422
-rw-r--r--modules/fatal-signal2
-rw-r--r--modules/sigprocmask26
9 files changed, 324 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 5d46d88438..8393e8cb10 100644
--- 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.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 17e7244a03..1196121e03 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -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
diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index 8a3a99c368..f85b60f418 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -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
index 0000000000..149d27003a
--- /dev/null
+++ b/lib/sigprocmask.c
@@ -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
index 0000000000..f88351f477
--- /dev/null
+++ b/lib/sigprocmask.h
@@ -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
diff --git a/m4/fatal-signal.m4 b/m4/fatal-signal.m4
index 062f6e0a77..c188b14395 100644
--- a/m4/fatal-signal.m4
+++ b/m4/fatal-signal.m4
@@ -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)
])
diff --git a/m4/signalblocking.m4 b/m4/signalblocking.m4
index fe91f29846..bb120f55cc 100644
--- a/m4/signalblocking.m4
+++ b/m4/signalblocking.m4
@@ -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)
])
diff --git a/modules/fatal-signal b/modules/fatal-signal
index dce33bd423..4365b3a61e 100644
--- a/modules/fatal-signal
+++ b/modules/fatal-signal
@@ -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
index 0000000000..314e4be450
--- /dev/null
+++ b/modules/sigprocmask
@@ -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
+