Mercurial > hg > octave-lyh > gnulib-hg
changeset 7503:a55a9e67f244
New module 'sigprocmask'.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 16 Oct 2006 11:55:35 +0000 |
parents | b535f4842828 |
children | e44e7c739d9c |
files | ChangeLog MODULES.html.sh lib/fatal-signal.c lib/sigprocmask.c lib/sigprocmask.h m4/fatal-signal.m4 m4/signalblocking.m4 modules/fatal-signal modules/sigprocmask |
diffstat | 9 files changed, 324 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- 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.
--- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1849,6 +1849,7 @@ func_module regex func_module rename func_module rmdir + func_module sigprocmask func_module ssize_t func_module strtok_r func_module sys_stat
--- 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 @@ /* ========================================================================= */ -#if HAVE_POSIX_SIGNALBLOCKING - static sigset_t fatal_signal_set; static void @@ -269,20 +268,3 @@ 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
new file mode 100644 --- /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; +}
new file mode 100644 --- /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
--- 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) ])
--- 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 @@ # 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) +])
--- a/modules/fatal-signal +++ b/modules/fatal-signal @@ -5,13 +5,13 @@ 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
new file mode 100644 --- /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 +