Skip to content

Commit 8ec2dcc

Browse files
committed
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.
1 parent 3d900e7 commit 8ec2dcc

13 files changed

+1181
-2
lines changed

compat.h

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#ifndef __COMPAT_H__
22
#define __COMPAT_H__
33

4+
#ifndef __SUSECONDS_T_TYPE
5+
typedef long suseconds_t;
6+
#endif
7+
48
#ifdef WIN32
59

610
#include <windows.h>

lib/.gitignore

Whitespace-only changes.

lib/Makefile.am

+55-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# the same distribution terms as the rest of that program.
1010
#
1111
# Generated by gnulib-tool.
12-
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-conditional-dependencies --no-libtool --macro-prefix=gl memmem
12+
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files memmem sigaction signal
1313

1414
AUTOMAKE_OPTIONS = 1.5 gnits
1515

@@ -102,6 +102,60 @@ EXTRA_libgnu_a_SOURCES += memmem.c
102102

103103
## end gnulib module memmem-simple
104104

105+
## begin gnulib module sigaction
106+
107+
108+
EXTRA_DIST += sig-handler.h sigaction.c
109+
110+
EXTRA_libgnu_a_SOURCES += sigaction.c
111+
112+
## end gnulib module sigaction
113+
114+
## begin gnulib module signal
115+
116+
BUILT_SOURCES += signal.h
117+
118+
# We need the following in order to create <signal.h> when the system
119+
# doesn't have a complete one.
120+
signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
121+
$(AM_V_GEN)rm -f $@-t $@ && \
122+
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
123+
sed -e 's|@''GUARD_PREFIX''@|GL|g' \
124+
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
125+
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
126+
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
127+
-e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
128+
-e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \
129+
-e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
130+
-e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
131+
-e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
132+
-e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
133+
-e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
134+
-e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
135+
-e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \
136+
-e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \
137+
-e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \
138+
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
139+
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
140+
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
141+
< $(srcdir)/signal.in.h; \
142+
} > $@-t && \
143+
mv $@-t $@
144+
MOSTLYCLEANFILES += signal.h signal.h-t
145+
146+
EXTRA_DIST += signal.in.h
147+
148+
## end gnulib module signal
149+
150+
## begin gnulib module sigprocmask
151+
152+
153+
EXTRA_DIST += sigprocmask.c
154+
155+
EXTRA_libgnu_a_SOURCES += sigprocmask.c
156+
157+
## end gnulib module sigprocmask
158+
105159
## begin gnulib module stddef
106160

107161
BUILT_SOURCES += $(STDDEF_H)

lib/sig-handler.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* Convenience declarations when working with <signal.h>.
2+
3+
Copyright (C) 2008-2011 Free Software Foundation, Inc.
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
17+
18+
#ifndef _GL_SIG_HANDLER_H
19+
#define _GL_SIG_HANDLER_H
20+
21+
#include <signal.h>
22+
23+
/* Convenience type when working with signal handlers. */
24+
typedef void (*sa_handler_t) (int);
25+
26+
/* Return the handler of a signal, as a sa_handler_t value regardless
27+
of its true type. The resulting function can be compared to
28+
special values like SIG_IGN but it is not portable to call it. */
29+
static inline sa_handler_t
30+
get_handler (struct sigaction const *a)
31+
{
32+
#ifdef SA_SIGINFO
33+
/* POSIX says that special values like SIG_IGN can only occur when
34+
action.sa_flags does not contain SA_SIGINFO. But in Linux 2.4,
35+
for example, sa_sigaction and sa_handler are aliases and a signal
36+
is ignored if sa_sigaction (after casting) equals SIG_IGN. So
37+
use (and cast) sa_sigaction in that case. */
38+
if (a->sa_flags & SA_SIGINFO)
39+
return (sa_handler_t) a->sa_sigaction;
40+
#endif
41+
return a->sa_handler;
42+
}
43+
44+
#endif /* _GL_SIG_HANDLER_H */

lib/sigaction.c

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/* POSIX compatible signal blocking.
2+
Copyright (C) 2008-2011 Free Software Foundation, Inc.
3+
Written by Eric Blake <[email protected]>, 2008.
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
17+
18+
#include <config.h>
19+
20+
/* Specification. */
21+
#include <signal.h>
22+
23+
#include <errno.h>
24+
#include <stdint.h>
25+
#include <stdlib.h>
26+
27+
/* This implementation of sigaction is tailored to Woe32 behavior:
28+
signal() has SysV semantics (ie. the handler is uninstalled before
29+
it is invoked). This is an inherent data race if an asynchronous
30+
signal is sent twice in a row before we can reinstall our handler,
31+
but there's nothing we can do about it. Meanwhile, sigprocmask()
32+
is not present, and while we can use the gnulib replacement to
33+
provide critical sections, it too suffers from potential data races
34+
in the face of an ill-timed asynchronous signal. And we compound
35+
the situation by reading static storage in a signal handler, which
36+
POSIX warns is not generically async-signal-safe. Oh well.
37+
38+
Additionally:
39+
- We don't implement SA_NOCLDSTOP or SA_NOCLDWAIT, because SIGCHLD
40+
is not defined.
41+
- We don't implement SA_ONSTACK, because sigaltstack() is not present.
42+
- We ignore SA_RESTART, because blocking Win32 calls are not interrupted
43+
anyway when an asynchronous signal occurs, and the MSVCRT runtime
44+
never sets errno to EINTR.
45+
- We don't implement SA_SIGINFO because it is impossible to do so
46+
portably.
47+
48+
POSIX states that an application should not mix signal() and
49+
sigaction(). We support the use of signal() within the gnulib
50+
sigprocmask() substitute, but all other application code linked
51+
with this module should stick with only sigaction(). */
52+
53+
/* Check some of our assumptions. */
54+
#if defined SIGCHLD || defined HAVE_SIGALTSTACK || defined HAVE_SIGINTERRUPT
55+
# error "Revisit the assumptions made in the sigaction module"
56+
#endif
57+
58+
/* Out-of-range substitutes make a good fallback for uncatchable
59+
signals. */
60+
#ifndef SIGKILL
61+
# define SIGKILL (-1)
62+
#endif
63+
#ifndef SIGSTOP
64+
# define SIGSTOP (-1)
65+
#endif
66+
67+
/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias
68+
for the signal SIGABRT. Only one signal handler is stored for both
69+
SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */
70+
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
71+
# undef SIGABRT_COMPAT
72+
# define SIGABRT_COMPAT 6
73+
#endif
74+
75+
/* A signal handler. */
76+
typedef void (*handler_t) (int signal);
77+
78+
/* Set of current actions. If sa_handler for an entry is NULL, then
79+
that signal is not currently handled by the sigaction handler. */
80+
static struct sigaction volatile action_array[NSIG] /* = 0 */;
81+
82+
/* Signal handler that is installed for signals. */
83+
static void
84+
sigaction_handler (int sig)
85+
{
86+
handler_t handler;
87+
sigset_t mask;
88+
sigset_t oldmask;
89+
int saved_errno = errno;
90+
if (sig < 0 || NSIG <= sig || !action_array[sig].sa_handler)
91+
{
92+
/* Unexpected situation; be careful to avoid recursive abort. */
93+
if (sig == SIGABRT)
94+
signal (SIGABRT, SIG_DFL);
95+
abort ();
96+
}
97+
98+
/* Reinstall the signal handler when required; otherwise update the
99+
bookkeeping so that the user's handler may call sigaction and get
100+
accurate results. We know the signal isn't currently blocked, or
101+
we wouldn't be in its handler, therefore we know that we are not
102+
interrupting a sigaction() call. There is a race where any
103+
asynchronous instance of the same signal occurring before we
104+
reinstall the handler will trigger the default handler; oh
105+
well. */
106+
handler = action_array[sig].sa_handler;
107+
if ((action_array[sig].sa_flags & SA_RESETHAND) == 0)
108+
signal (sig, sigaction_handler);
109+
else
110+
action_array[sig].sa_handler = NULL;
111+
112+
/* Block appropriate signals. */
113+
mask = action_array[sig].sa_mask;
114+
if ((action_array[sig].sa_flags & SA_NODEFER) == 0)
115+
sigaddset (&mask, sig);
116+
sigprocmask (SIG_BLOCK, &mask, &oldmask);
117+
118+
/* Invoke the user's handler, then restore prior mask. */
119+
errno = saved_errno;
120+
handler (sig);
121+
saved_errno = errno;
122+
sigprocmask (SIG_SETMASK, &oldmask, NULL);
123+
errno = saved_errno;
124+
}
125+
126+
/* Change and/or query the action that will be taken on delivery of
127+
signal SIG. If not NULL, ACT describes the new behavior. If not
128+
NULL, OACT is set to the prior behavior. Return 0 on success, or
129+
set errno and return -1 on failure. */
130+
int
131+
sigaction (int sig, const struct sigaction *restrict act,
132+
struct sigaction *restrict oact)
133+
{
134+
sigset_t mask;
135+
sigset_t oldmask;
136+
int saved_errno;
137+
138+
if (sig < 0 || NSIG <= sig || sig == SIGKILL || sig == SIGSTOP
139+
|| (act && act->sa_handler == SIG_ERR))
140+
{
141+
errno = EINVAL;
142+
return -1;
143+
}
144+
145+
#ifdef SIGABRT_COMPAT
146+
if (sig == SIGABRT_COMPAT)
147+
sig = SIGABRT;
148+
#endif
149+
150+
/* POSIX requires sigaction() to be async-signal-safe. In other
151+
words, if an asynchronous signal can occur while we are anywhere
152+
inside this function, the user's handler could then call
153+
sigaction() recursively and expect consistent results. We meet
154+
this rule by using sigprocmask to block all signals before
155+
modifying any data structure that could be read from a signal
156+
handler; this works since we know that the gnulib sigprocmask
157+
replacement does not try to use sigaction() from its handler. */
158+
if (!act && !oact)
159+
return 0;
160+
sigfillset (&mask);
161+
sigprocmask (SIG_BLOCK, &mask, &oldmask);
162+
if (oact)
163+
{
164+
if (action_array[sig].sa_handler)
165+
*oact = action_array[sig];
166+
else
167+
{
168+
/* Safe to change the handler at will here, since all
169+
signals are currently blocked. */
170+
oact->sa_handler = signal (sig, SIG_DFL);
171+
if (oact->sa_handler == SIG_ERR)
172+
goto failure;
173+
signal (sig, oact->sa_handler);
174+
oact->sa_flags = SA_RESETHAND | SA_NODEFER;
175+
sigemptyset (&oact->sa_mask);
176+
}
177+
}
178+
179+
if (act)
180+
{
181+
/* Safe to install the handler before updating action_array,
182+
since all signals are currently blocked. */
183+
if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN)
184+
{
185+
if (signal (sig, act->sa_handler) == SIG_ERR)
186+
goto failure;
187+
action_array[sig].sa_handler = NULL;
188+
}
189+
else
190+
{
191+
if (signal (sig, sigaction_handler) == SIG_ERR)
192+
goto failure;
193+
action_array[sig] = *act;
194+
}
195+
}
196+
sigprocmask (SIG_SETMASK, &oldmask, NULL);
197+
return 0;
198+
199+
failure:
200+
saved_errno = errno;
201+
sigprocmask (SIG_SETMASK, &oldmask, NULL);
202+
errno = saved_errno;
203+
return -1;
204+
}

0 commit comments

Comments
 (0)