Mercurial > hg > octave-jordi > gnulib-hg
annotate lib/sigaction.c @ 18029:e4a13d95b503
mgetgroups: port to strict OS X
* doc/glibc-functions/getgrouplist.texi (getgrouplist):
Document the getgrouplist problem.
* lib/mgetgroups.c (getgrouplist_gids) [HAVE_GETGROUPLIST]:
New macro.
(mgetgroups): Use it.
* m4/mgetgroups.m4 (gl_MGETGROUPS):
Check for OS X signature for getgrouplist.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Sun, 28 Jun 2015 23:43:35 -0700 |
parents | ab58d4870664 |
children |
rev | line source |
---|---|
10229 | 1 /* POSIX compatible signal blocking. |
17848 | 2 Copyright (C) 2008-2015 Free Software Foundation, Inc. |
10229 | 3 Written by Eric Blake <ebb9@byu.net>, 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 | |
16242
59c686e5b2df
Talk about "native Windows API", not "Woe32".
Bruno Haible <bruno@clisp.org>
parents:
16214
diff
changeset
|
27 /* This implementation of sigaction is tailored to native Windows behavior: |
10229 | 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 | |
10236
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
38 Additionally: |
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
39 - We don't implement SA_NOCLDSTOP or SA_NOCLDWAIT, because SIGCHLD |
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
40 is not defined. |
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
41 - We don't implement SA_ONSTACK, because sigaltstack() is not present. |
16214
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
42 - We ignore SA_RESTART, because blocking native Windows API calls are |
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
43 not interrupted anyway when an asynchronous signal occurs, and the |
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
44 MSVCRT runtime never sets errno to EINTR. |
10236
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
45 - We don't implement SA_SIGINFO because it is impossible to do so |
d7f97416cbe1
Define SA_RESTART also for mingw.
Bruno Haible <bruno@clisp.org>
parents:
10229
diff
changeset
|
46 portably. |
10229 | 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 | |
10689
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
67 /* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
68 for the signal SIGABRT. Only one signal handler is stored for both |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
69 SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
70 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
71 # undef SIGABRT_COMPAT |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
72 # define SIGABRT_COMPAT 6 |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
73 #endif |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
74 |
10229 | 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) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
10689
diff
changeset
|
94 signal (SIGABRT, SIG_DFL); |
10229 | 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 | |
14380
5cee7a3cd6ca
maint: adjust cpp indentation for my modules, as well
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
145 #ifdef SIGABRT_COMPAT |
10689
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
146 if (sig == SIGABRT_COMPAT) |
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
147 sig = SIGABRT; |
14380
5cee7a3cd6ca
maint: adjust cpp indentation for my modules, as well
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
148 #endif |
10689
5fbf24129e48
Take into account the role of SIGABRT_COMPAT on Windows 2008.
Bruno Haible <bruno@clisp.org>
parents:
10236
diff
changeset
|
149 |
10229 | 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 } |