mirror of https://github.com/GOSTSec/sgminer
Con Kolivas
14 years ago
13 changed files with 1181 additions and 2 deletions
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* Convenience declarations when working with <signal.h>.
|
||||
|
||||
Copyright (C) 2008-2011 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 */ |
@ -0,0 +1,204 @@
@@ -0,0 +1,204 @@
|
||||
/* POSIX compatible signal blocking.
|
||||
Copyright (C) 2008-2011 Free Software Foundation, Inc. |
||||
Written by Eric Blake <ebb9@byu.net>, 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: |
||||
- We don't implement SA_NOCLDSTOP or SA_NOCLDWAIT, because SIGCHLD |
||||
is not defined. |
||||
- We don't implement SA_ONSTACK, because sigaltstack() is not present. |
||||
- We ignore SA_RESTART, because blocking Win32 calls are not interrupted |
||||
anyway when an asynchronous signal occurs, and the MSVCRT runtime |
||||
never sets errno to EINTR. |
||||
- We don't implement SA_SIGINFO because it is impossible to do so |
||||
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 |
||||
|
||||
/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias
|
||||
for the signal SIGABRT. Only one signal handler is stored for both |
||||
SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ |
||||
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
||||
# undef SIGABRT_COMPAT |
||||
# define SIGABRT_COMPAT 6 |
||||
#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; |
||||
} |
||||
|
||||
#ifdef SIGABRT_COMPAT |
||||
if (sig == SIGABRT_COMPAT) |
||||
sig = SIGABRT; |
||||
#endif |
||||
|
||||
/* 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; |
||||
} |
@ -0,0 +1,376 @@
@@ -0,0 +1,376 @@
|
||||
/* A GNU-like <signal.h>.
|
||||
|
||||
Copyright (C) 2006-2011 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/>. */
|
||||
|
||||
#if __GNUC__ >= 3 |
||||
@PRAGMA_SYSTEM_HEADER@ |
||||
#endif |
||||
@PRAGMA_COLUMNS@ |
||||
|
||||
#if defined __need_sig_atomic_t || defined __need_sigset_t |
||||
/* Special invocation convention inside glibc header files. */ |
||||
|
||||
# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@ |
||||
|
||||
#else |
||||
/* Normal invocation convention. */ |
||||
|
||||
#ifndef _@GUARD_PREFIX@_SIGNAL_H |
||||
|
||||
/* The include_next requires a split double-inclusion guard. */ |
||||
#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@ |
||||
|
||||
#ifndef _@GUARD_PREFIX@_SIGNAL_H |
||||
#define _@GUARD_PREFIX@_SIGNAL_H |
||||
|
||||
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ |
||||
|
||||
/* The definition of _GL_ARG_NONNULL is copied here. */ |
||||
|
||||
/* The definition of _GL_WARN_ON_USE is copied here. */ |
||||
|
||||
/* Define pid_t, uid_t.
|
||||
Also, mingw defines sigset_t not in <signal.h>, but in <sys/types.h>. */ |
||||
#include <sys/types.h> |
||||
|
||||
/* On AIX, sig_atomic_t already includes volatile. C99 requires that
|
||||
'volatile sig_atomic_t' ignore the extra modifier, but C89 did not. |
||||
Hence, redefine this to a non-volatile type as needed. */ |
||||
#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ |
||||
# if !GNULIB_defined_sig_atomic_t |
||||
typedef int rpl_sig_atomic_t; |
||||
# undef sig_atomic_t |
||||
# define sig_atomic_t rpl_sig_atomic_t |
||||
# define GNULIB_defined_sig_atomic_t 1 |
||||
# endif |
||||
#endif |
||||
|
||||
/* A set or mask of signals. */ |
||||
#if !@HAVE_SIGSET_T@ |
||||
# if !GNULIB_defined_sigset_t |
||||
typedef unsigned int sigset_t; |
||||
# define GNULIB_defined_sigset_t 1 |
||||
# endif |
||||
#endif |
||||
|
||||
/* Define sighandler_t, the type of signal handlers. A GNU extension. */ |
||||
#if !@HAVE_SIGHANDLER_T@ |
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
# if !GNULIB_defined_sighandler_t |
||||
typedef void (*sighandler_t) (int); |
||||
# define GNULIB_defined_sighandler_t 1 |
||||
# endif |
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
#endif |
||||
|
||||
|
||||
#if @GNULIB_SIGNAL_H_SIGPIPE@ |
||||
# ifndef SIGPIPE |
||||
/* Define SIGPIPE to a value that does not overlap with other signals. */ |
||||
# define SIGPIPE 13 |
||||
# define GNULIB_defined_SIGPIPE 1 |
||||
/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask',
|
||||
'write', 'stdio'. */ |
||||
# endif |
||||
#endif |
||||
|
||||
|
||||
/* Maximum signal number + 1. */ |
||||
#ifndef NSIG |
||||
# if defined __TANDEM |
||||
# define NSIG 32 |
||||
# endif |
||||
#endif |
||||
|
||||
|
||||
#if @GNULIB_SIGPROCMASK@ |
||||
# if !@HAVE_POSIX_SIGNALBLOCKING@ |
||||
|
||||
/* Maximum signal number + 1. */ |
||||
# ifndef NSIG |
||||
# define NSIG 32 |
||||
# endif |
||||
|
||||
/* This code supports only 32 signals. */ |
||||
# if !GNULIB_defined_verify_NSIG_constraint |
||||
typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1]; |
||||
# define GNULIB_defined_verify_NSIG_constraint 1 |
||||
# endif |
||||
|
||||
# endif |
||||
|
||||
/* Test whether a given signal is contained in a signal set. */ |
||||
# if @HAVE_POSIX_SIGNALBLOCKING@ |
||||
/* This function is defined as a macro on MacOS X. */ |
||||
# if defined __cplusplus && defined GNULIB_NAMESPACE |
||||
# undef sigismember |
||||
# endif |
||||
# else |
||||
_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig) |
||||
_GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig)); |
||||
_GL_CXXALIASWARN (sigismember); |
||||
|
||||
/* Initialize a signal set to the empty set. */ |
||||
# if @HAVE_POSIX_SIGNALBLOCKING@ |
||||
/* This function is defined as a macro on MacOS X. */ |
||||
# if defined __cplusplus && defined GNULIB_NAMESPACE |
||||
# undef sigemptyset |
||||
# endif |
||||
# else |
||||
_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set)); |
||||
_GL_CXXALIASWARN (sigemptyset); |
||||
|
||||
/* Add a signal to a signal set. */ |
||||
# if @HAVE_POSIX_SIGNALBLOCKING@ |
||||
/* This function is defined as a macro on MacOS X. */ |
||||
# if defined __cplusplus && defined GNULIB_NAMESPACE |
||||
# undef sigaddset |
||||
# endif |
||||
# else |
||||
_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig) |
||||
_GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig)); |
||||
_GL_CXXALIASWARN (sigaddset); |
||||
|
||||
/* Remove a signal from a signal set. */ |
||||
# if @HAVE_POSIX_SIGNALBLOCKING@ |
||||
/* This function is defined as a macro on MacOS X. */ |
||||
# if defined __cplusplus && defined GNULIB_NAMESPACE |
||||
# undef sigdelset |
||||
# endif |
||||
# else |
||||
_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig) |
||||
_GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig)); |
||||
_GL_CXXALIASWARN (sigdelset); |
||||
|
||||
/* Fill a signal set with all possible signals. */ |
||||
# if @HAVE_POSIX_SIGNALBLOCKING@ |
||||
/* This function is defined as a macro on MacOS X. */ |
||||
# if defined __cplusplus && defined GNULIB_NAMESPACE |
||||
# undef sigfillset |
||||
# endif |
||||
# else |
||||
_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set)); |
||||
_GL_CXXALIASWARN (sigfillset); |
||||
|
||||
/* Return the set of those blocked signals that are pending. */ |
||||
# if !@HAVE_POSIX_SIGNALBLOCKING@ |
||||
_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set)); |
||||
_GL_CXXALIASWARN (sigpending); |
||||
|
||||
/* 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. */ |
||||
# if !@HAVE_POSIX_SIGNALBLOCKING@ |
||||
# 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; */ |
||||
_GL_FUNCDECL_SYS (sigprocmask, int, |
||||
(int operation, const sigset_t *set, sigset_t *old_set)); |
||||
# endif |
||||
_GL_CXXALIAS_SYS (sigprocmask, int, |
||||
(int operation, const sigset_t *set, sigset_t *old_set)); |
||||
_GL_CXXALIASWARN (sigprocmask); |
||||
|
||||
/* Install the handler FUNC for signal SIG, and return the previous
|
||||
handler. */ |
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
# if !GNULIB_defined_function_taking_int_returning_void_t |
||||
typedef void (*_gl_function_taking_int_returning_void_t) (int); |
||||
# define GNULIB_defined_function_taking_int_returning_void_t 1 |
||||
# endif |
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
# if !@HAVE_POSIX_SIGNALBLOCKING@ |
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
||||
# define signal rpl_signal |
||||
# endif |
||||
_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t, |
||||
(int sig, _gl_function_taking_int_returning_void_t func)); |
||||
_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t, |
||||
(int sig, _gl_function_taking_int_returning_void_t func)); |
||||
# else |
||||
_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t, |
||||
(int sig, _gl_function_taking_int_returning_void_t func)); |
||||
# endif |
||||
_GL_CXXALIASWARN (signal); |
||||
|
||||
/* Raise signal SIG. */ |
||||
# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE |
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
||||
# undef raise |
||||
# define raise rpl_raise |
||||
# endif |
||||
_GL_FUNCDECL_RPL (raise, int, (int sig)); |
||||
_GL_CXXALIAS_RPL (raise, int, (int sig)); |
||||
# else |
||||
_GL_CXXALIAS_SYS (raise, int, (int sig)); |
||||
# endif |
||||
_GL_CXXALIASWARN (raise); |
||||
|
||||
#elif defined GNULIB_POSIXCHECK |
||||
# undef sigaddset |
||||
# if HAVE_RAW_DECL_SIGADDSET |
||||
_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigdelset |
||||
# if HAVE_RAW_DECL_SIGDELSET |
||||
_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigemptyset |
||||
# if HAVE_RAW_DECL_SIGEMPTYSET |
||||
_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigfillset |
||||
# if HAVE_RAW_DECL_SIGFILLSET |
||||
_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigismember |
||||
# if HAVE_RAW_DECL_SIGISMEMBER |
||||
_GL_WARN_ON_USE (sigismember, "sigismember is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigpending |
||||
# if HAVE_RAW_DECL_SIGPENDING |
||||
_GL_WARN_ON_USE (sigpending, "sigpending is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
# undef sigprocmask |
||||
# if HAVE_RAW_DECL_SIGPROCMASK |
||||
_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - " |
||||
"use the gnulib module sigprocmask for portability"); |
||||
# endif |
||||
#endif /* @GNULIB_SIGPROCMASK@ */ |
||||
|
||||
|
||||
#if @GNULIB_SIGACTION@ |
||||
# if !@HAVE_SIGACTION@ |
||||
|
||||
# if !@HAVE_SIGINFO_T@ |
||||
|
||||
# if !GNULIB_defined_siginfo_types |
||||
|
||||
/* 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; |
||||
|
||||
# define GNULIB_defined_siginfo_types 1 |
||||
# endif |
||||
|
||||
# endif /* !@HAVE_SIGINFO_T@ */ |
||||
|
||||
/* We assume that platforms which lack the sigaction() function also lack
|
||||
the 'struct sigaction' type, and vice versa. */ |
||||
|
||||
# if !GNULIB_defined_struct_sigaction |
||||
|
||||
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 |
||||
# define SA_RESTART 4 |
||||
|
||||
# define GNULIB_defined_struct_sigaction 1 |
||||
# endif |
||||
|
||||
_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict, |
||||
struct sigaction *restrict)); |
||||
|
||||
# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ |
||||
|
||||
# define sa_sigaction sa_handler |
||||
|
||||
# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */ |
||||
|
||||
_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict, |
||||
struct sigaction *restrict)); |
||||
_GL_CXXALIASWARN (sigaction); |
||||
|
||||
#elif defined GNULIB_POSIXCHECK |
||||
# undef sigaction |
||||
# if HAVE_RAW_DECL_SIGACTION |
||||
_GL_WARN_ON_USE (sigaction, "sigaction is unportable - " |
||||
"use the gnulib module sigaction for portability"); |
||||
# endif |
||||
#endif |
||||
|
||||
/* Some systems don't have SA_NODEFER. */ |
||||
#ifndef SA_NODEFER |
||||
# define SA_NODEFER 0 |
||||
#endif |
||||
|
||||
|
||||
#endif /* _@GUARD_PREFIX@_SIGNAL_H */ |
||||
#endif /* _@GUARD_PREFIX@_SIGNAL_H */ |
||||
#endif |
@ -0,0 +1,329 @@
@@ -0,0 +1,329 @@
|
||||
/* POSIX compatible signal blocking.
|
||||
Copyright (C) 2006-2011 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 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> |
||||
|
||||
/* 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 |
||||
|
||||
/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias
|
||||
for the signal SIGABRT. Only one signal handler is stored for both |
||||
SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ |
||||
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
||||
# undef SIGABRT_COMPAT |
||||
# define SIGABRT_COMPAT 6 |
||||
#endif |
||||
#ifdef SIGABRT_COMPAT |
||||
# define SIGABRT_COMPAT_MASK (1U << SIGABRT_COMPAT) |
||||
#else |
||||
# define SIGABRT_COMPAT_MASK 0 |
||||
#endif |
||||
|
||||
typedef void (*handler_t) (int); |
||||
|
||||
/* Handling of gnulib defined signals. */ |
||||
|
||||
#if GNULIB_defined_SIGPIPE |
||||
static handler_t SIGPIPE_handler = SIG_DFL; |
||||
#endif |
||||
|
||||
#if GNULIB_defined_SIGPIPE |
||||
static handler_t |
||||
ext_signal (int sig, handler_t handler) |
||||
{ |
||||
switch (sig) |
||||
{ |
||||
case SIGPIPE: |
||||
{ |
||||
handler_t old_handler = SIGPIPE_handler; |
||||
SIGPIPE_handler = handler; |
||||
return old_handler; |
||||
} |
||||
default: /* System defined signal */ |
||||
return signal (sig, handler); |
||||
} |
||||
} |
||||
# define signal ext_signal |
||||
#endif |
||||
|
||||
int |
||||
sigismember (const sigset_t *set, int sig) |
||||
{ |
||||
if (sig >= 0 && sig < NSIG) |
||||
{ |
||||
#ifdef SIGABRT_COMPAT |
||||
if (sig == SIGABRT_COMPAT) |
||||
sig = SIGABRT; |
||||
#endif |
||||
|
||||
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) |
||||
{ |
||||
#ifdef SIGABRT_COMPAT |
||||
if (sig == SIGABRT_COMPAT) |
||||
sig = SIGABRT; |
||||
#endif |
||||
|
||||
*set |= 1U << sig; |
||||
return 0; |
||||
} |
||||
else |
||||
{ |
||||
errno = EINVAL; |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
int |
||||
sigdelset (sigset_t *set, int sig) |
||||
{ |
||||
if (sig >= 0 && sig < NSIG) |
||||
{ |
||||
#ifdef SIGABRT_COMPAT |
||||
if (sig == SIGABRT_COMPAT) |
||||
sig = SIGABRT; |
||||
#endif |
||||
|
||||
*set &= ~(1U << sig); |
||||
return 0; |
||||
} |
||||
else |
||||
{ |
||||
errno = EINVAL; |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
|
||||
int |
||||
sigfillset (sigset_t *set) |
||||
{ |
||||
*set = ((2U << (NSIG - 1)) - 1) & ~ SIGABRT_COMPAT_MASK; |
||||
return 0; |
||||
} |
||||
|
||||
/* Set of currently blocked signals. */ |
||||
static volatile 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) |
||||
{ |
||||
/* 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; |
||||
} |
||||
|
||||
int |
||||
sigpending (sigset_t *set) |
||||
{ |
||||
sigset_t pending = 0; |
||||
int sig; |
||||
|
||||
for (sig = 0; sig < NSIG; sig++) |
||||
if (pending_array[sig]) |
||||
pending |= 1U << sig; |
||||
*set = pending; |
||||
return 0; |
||||
} |
||||
|
||||
/* The previous signal handlers.
|
||||
Only the array elements corresponding to blocked signals are relevant. */ |
||||
static volatile 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, bypassing our rpl_signal replacement. |
||||
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[sig]) |
||||
raise (sig); |
||||
} |
||||
} |
||||
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) |
||||
{ |
||||
#ifdef SIGABRT_COMPAT |
||||
if (sig == SIGABRT_COMPAT) |
||||
sig = SIGABRT; |
||||
#endif |
||||
|
||||
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; |
||||
} |
||||
else |
||||
return signal (sig, handler); |
||||
} |
||||
else |
||||
{ |
||||
errno = EINVAL; |
||||
return SIG_ERR; |
||||
} |
||||
} |
||||
|
||||
#if GNULIB_defined_SIGPIPE |
||||
/* Raise the signal SIG. */ |
||||
int |
||||
rpl_raise (int sig) |
||||
# undef raise |
||||
{ |
||||
switch (sig) |
||||
{ |
||||
case SIGPIPE: |
||||
if (blocked_set & (1U << sig)) |
||||
pending_array[sig] = 1; |
||||
else |
||||
{ |
||||
handler_t handler = SIGPIPE_handler; |
||||
if (handler == SIG_DFL) |
||||
exit (128 + SIGPIPE); |
||||
else if (handler != SIG_IGN) |
||||
(*handler) (sig); |
||||
} |
||||
return 0; |
||||
default: /* System defined signal */ |
||||
return raise (sig); |
||||
} |
||||
} |
||||
#endif |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
# sigaction.m4 serial 6 |
||||
dnl Copyright (C) 2008-2011 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], |
||||
[ |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
AC_CHECK_FUNCS_ONCE([sigaction]) |
||||
if test $ac_cv_func_sigaction = yes; then |
||||
AC_CHECK_MEMBERS([struct sigaction.sa_sigaction], , , |
||||
[[#include <signal.h>]]) |
||||
if test $ac_cv_member_struct_sigaction_sa_sigaction = no; then |
||||
HAVE_STRUCT_SIGACTION_SA_SIGACTION=0 |
||||
fi |
||||
else |
||||
HAVE_SIGACTION=0 |
||||
fi |
||||
]) |
||||
|
||||
# Prerequisites of the part of lib/signal.in.h and of lib/sigaction.c. |
||||
AC_DEFUN([gl_PREREQ_SIGACTION], |
||||
[ |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
AC_REQUIRE([AC_C_RESTRICT]) |
||||
AC_REQUIRE([AC_TYPE_UID_T]) |
||||
AC_REQUIRE([gl_PREREQ_SIG_HANDLER_H]) |
||||
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 |
||||
fi |
||||
]) |
||||
|
||||
# Prerequisites of lib/sig-handler.h. |
||||
AC_DEFUN([gl_PREREQ_SIG_HANDLER_H], |
||||
[ |
||||
AC_REQUIRE([AC_C_INLINE]) |
||||
]) |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
# signal_h.m4 serial 12 |
||||
dnl Copyright (C) 2007-2011 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_SIGNAL_H], |
||||
[ |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
gl_NEXT_HEADERS([signal.h]) |
||||
|
||||
# AIX declares sig_atomic_t to already include volatile, and C89 compilers |
||||
# then choke on 'volatile sig_atomic_t'. C99 requires that it compile. |
||||
AC_CHECK_TYPE([volatile sig_atomic_t], [], |
||||
[HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=0], [[ |
||||
#include <signal.h> |
||||
]]) |
||||
|
||||
AC_REQUIRE([AC_TYPE_UID_T]) |
||||
|
||||
dnl Persuade glibc <signal.h> to define sighandler_t. |
||||
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) |
||||
AC_CHECK_TYPE([sighandler_t], [], [HAVE_SIGHANDLER_T=0], [[ |
||||
#include <signal.h> |
||||
]]) |
||||
|
||||
dnl Check for declarations of anything we want to poison if the |
||||
dnl corresponding gnulib module is not in use. |
||||
gl_WARN_ON_USE_PREPARE([[#include <signal.h> |
||||
]], [sigaction sigaddset sigdelset sigemptyset sigfillset sigismember |
||||
sigpending sigprocmask]) |
||||
]) |
||||
|
||||
AC_DEFUN([gl_SIGNAL_MODULE_INDICATOR], |
||||
[ |
||||
dnl Use AC_REQUIRE here, so that the default settings are expanded once only. |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
gl_MODULE_INDICATOR_SET_VARIABLE([$1]) |
||||
dnl Define it also as a C macro, for the benefit of the unit tests. |
||||
gl_MODULE_INDICATOR_FOR_TESTS([$1]) |
||||
]) |
||||
|
||||
AC_DEFUN([gl_SIGNAL_H_DEFAULTS], |
||||
[ |
||||
GNULIB_SIGNAL_H_SIGPIPE=0; AC_SUBST([GNULIB_SIGNAL_H_SIGPIPE]) |
||||
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]) |
||||
HAVE_STRUCT_SIGACTION_SA_SIGACTION=1; |
||||
AC_SUBST([HAVE_STRUCT_SIGACTION_SA_SIGACTION]) |
||||
HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=1; |
||||
AC_SUBST([HAVE_TYPE_VOLATILE_SIG_ATOMIC_T]) |
||||
HAVE_SIGHANDLER_T=1; AC_SUBST([HAVE_SIGHANDLER_T]) |
||||
]) |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
# signalblocking.m4 serial 11 |
||||
dnl Copyright (C) 2001-2002, 2006-2011 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 available signal blocking primitives. Three different APIs exist: |
||||
# 1) POSIX: sigemptyset, sigaddset, sigprocmask |
||||
# 2) SYSV: sighold, sigrelse |
||||
# 3) BSD: sigblock, sigsetmask |
||||
# For simplicity, here we check only for the POSIX signal blocking. |
||||
AC_DEFUN([gl_SIGNALBLOCKING], |
||||
[ |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
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], [gl_cv_func_sigprocmask=1]) |
||||
fi |
||||
if test -z "$gl_cv_func_sigprocmask"; then |
||||
HAVE_POSIX_SIGNALBLOCKING=0 |
||||
fi |
||||
]) |
||||
|
||||
# Prerequisites of the part of lib/signal.in.h and of lib/sigprocmask.c. |
||||
AC_DEFUN([gl_PREREQ_SIGPROCMASK], |
||||
[ |
||||
AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) |
||||
AC_CHECK_TYPES([sigset_t], |
||||
[gl_cv_type_sigset_t=yes], [gl_cv_type_sigset_t=no], |
||||
[#include <signal.h> |
||||
/* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>. */ |
||||
#include <sys/types.h>]) |
||||
if test $gl_cv_type_sigset_t != yes; then |
||||
HAVE_SIGSET_T=0 |
||||
fi |
||||
dnl HAVE_SIGSET_T is 1 if the system lacks the sigprocmask function but has |
||||
dnl the sigset_t type. |
||||
AC_SUBST([HAVE_SIGSET_T]) |
||||
]) |
Loading…
Reference in new issue