-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Mingw suseconds_t and sigaction fixes.
Added typedef for suseconds_t for systems without this defined. Added signal/sigaction from gnulib because mingw is missing these.
- Loading branch information
Showing
13 changed files
with
1,181 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/* POSIX compatible signal blocking. | ||
Copyright (C) 2008-2011 Free Software Foundation, Inc. | ||
Written by Eric Blake <[email protected]>, 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; | ||
} |
Oops, something went wrong.