"Fossies" - the Fresh Open Source Software Archive 
Member "apr-1.7.0/threadproc/unix/signals.c" (7 Mar 2019, 12298 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "signals.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.6.5_vs_1.7.0.
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define INCL_DOSEXCEPTIONS /* for OS2 */
18 #include "apr_arch_threadproc.h"
19 #include "apr_private.h"
20 #include "apr_pools.h"
21 #include "apr_signal.h"
22 #include "apr_strings.h"
23
24 #include <assert.h>
25 #if APR_HAS_THREADS && APR_HAVE_PTHREAD_H
26 #include <pthread.h>
27 #endif
28
29 #ifdef SIGWAIT_TAKES_ONE_ARG
30 #define apr_sigwait(a,b) ((*(b)=sigwait((a)))<0?-1:0)
31 #else
32 #define apr_sigwait(a,b) sigwait((a),(b))
33 #endif
34
35 APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum)
36 {
37 #ifdef OS2
38 /* SIGTERM's don't work too well in OS/2 (only affects other EMX
39 * programs). CGIs may not be, esp. REXX scripts, so use a native
40 * call instead
41 */
42 if (signum == SIGTERM) {
43 return APR_OS2_STATUS(DosSendSignalException(proc->pid,
44 XCPT_SIGNAL_BREAK));
45 }
46 #endif /* OS2 */
47
48 if (kill(proc->pid, signum) == -1) {
49 return errno;
50 }
51
52 return APR_SUCCESS;
53 }
54
55
56 #if APR_HAVE_SIGACTION
57
58 #if defined(__NetBSD__) || defined(DARWIN)
59 static void avoid_zombies(int signo)
60 {
61 int exit_status;
62
63 while (waitpid(-1, &exit_status, WNOHANG) > 0) {
64 /* do nothing */
65 }
66 }
67 #endif /* DARWIN */
68
69 /*
70 * Replace standard signal() with the more reliable sigaction equivalent
71 * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
72 * (the version that does not automatically restart system calls).
73 */
74 APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func)
75 {
76 struct sigaction act, oact;
77
78 act.sa_handler = func;
79 sigemptyset(&act.sa_mask);
80 act.sa_flags = 0;
81 #ifdef SA_INTERRUPT /* SunOS */
82 act.sa_flags |= SA_INTERRUPT;
83 #endif
84 #if defined(__osf__) && defined(__alpha)
85 /* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */
86
87 /* this is required on Tru64 to cause child processes to
88 * disappear gracefully - XPG4 compatible
89 */
90 if ((signo == SIGCHLD) && (func == SIG_IGN)) {
91 act.sa_flags |= SA_NOCLDWAIT;
92 }
93 #endif
94 #if defined(__NetBSD__) || defined(DARWIN)
95 /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies,
96 * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in
97 * the handler to avoid zombies
98 */
99 if ((signo == SIGCHLD) && (func == SIG_IGN)) {
100 act.sa_handler = avoid_zombies;
101 }
102 #endif
103 if (sigaction(signo, &act, &oact) < 0)
104 return SIG_ERR;
105 return oact.sa_handler;
106 }
107
108 #endif /* HAVE_SIGACTION */
109
110 /* AC_DECL_SYS_SIGLIST defines either of these symbols depending
111 * on the version of autoconf used. */
112 #if defined(SYS_SIGLIST_DECLARED) || HAVE_DECL_SYS_SIGLIST
113
114 void apr_signal_init(apr_pool_t *pglobal)
115 {
116 }
117 const char *apr_signal_description_get(int signum)
118 {
119 return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)";
120 }
121
122 #else /* !(SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST) */
123
124 /* we need to roll our own signal description stuff */
125
126 #if defined(NSIG)
127 #define APR_NUMSIG NSIG
128 #elif defined(_NSIG)
129 #define APR_NUMSIG _NSIG
130 #elif defined(__NSIG)
131 #define APR_NUMSIG __NSIG
132 #else
133 #define APR_NUMSIG 33 /* breaks on OS/390 with < 33; 32 is o.k. for most */
134 #endif
135
136 static const char *signal_description[APR_NUMSIG];
137
138 #define store_desc(index, string) \
139 do { \
140 if (index >= APR_NUMSIG) { \
141 assert(index < APR_NUMSIG); \
142 } \
143 else { \
144 signal_description[index] = string; \
145 } \
146 } while (0)
147
148 void apr_signal_init(apr_pool_t *pglobal)
149 {
150 int sig;
151
152 store_desc(0, "Signal 0");
153
154 #ifdef SIGHUP
155 store_desc(SIGHUP, "Hangup");
156 #endif
157 #ifdef SIGINT
158 store_desc(SIGINT, "Interrupt");
159 #endif
160 #ifdef SIGQUIT
161 store_desc(SIGQUIT, "Quit");
162 #endif
163 #ifdef SIGILL
164 store_desc(SIGILL, "Illegal instruction");
165 #endif
166 #ifdef SIGTRAP
167 store_desc(SIGTRAP, "Trace/BPT trap");
168 #endif
169 #ifdef SIGIOT
170 store_desc(SIGIOT, "IOT instruction");
171 #endif
172 #ifdef SIGABRT
173 store_desc(SIGABRT, "Abort");
174 #endif
175 #ifdef SIGEMT
176 store_desc(SIGEMT, "Emulator trap");
177 #endif
178 #ifdef SIGFPE
179 store_desc(SIGFPE, "Arithmetic exception");
180 #endif
181 #ifdef SIGKILL
182 store_desc(SIGKILL, "Killed");
183 #endif
184 #ifdef SIGBUS
185 store_desc(SIGBUS, "Bus error");
186 #endif
187 #ifdef SIGSEGV
188 store_desc(SIGSEGV, "Segmentation fault");
189 #endif
190 #ifdef SIGSYS
191 store_desc(SIGSYS, "Bad system call");
192 #endif
193 #ifdef SIGPIPE
194 store_desc(SIGPIPE, "Broken pipe");
195 #endif
196 #ifdef SIGALRM
197 store_desc(SIGALRM, "Alarm clock");
198 #endif
199 #ifdef SIGTERM
200 store_desc(SIGTERM, "Terminated");
201 #endif
202 #ifdef SIGUSR1
203 store_desc(SIGUSR1, "User defined signal 1");
204 #endif
205 #ifdef SIGUSR2
206 store_desc(SIGUSR2, "User defined signal 2");
207 #endif
208 #ifdef SIGCLD
209 store_desc(SIGCLD, "Child status change");
210 #endif
211 #ifdef SIGCHLD
212 store_desc(SIGCHLD, "Child status change");
213 #endif
214 #ifdef SIGPWR
215 store_desc(SIGPWR, "Power-fail restart");
216 #endif
217 #ifdef SIGWINCH
218 store_desc(SIGWINCH, "Window changed");
219 #endif
220 #ifdef SIGURG
221 store_desc(SIGURG, "urgent socket condition");
222 #endif
223 #ifdef SIGPOLL
224 store_desc(SIGPOLL, "Pollable event occurred");
225 #endif
226 #ifdef SIGIO
227 store_desc(SIGIO, "socket I/O possible");
228 #endif
229 #ifdef SIGSTOP
230 store_desc(SIGSTOP, "Stopped (signal)");
231 #endif
232 #ifdef SIGTSTP
233 store_desc(SIGTSTP, "Stopped");
234 #endif
235 #ifdef SIGCONT
236 store_desc(SIGCONT, "Continued");
237 #endif
238 #ifdef SIGTTIN
239 store_desc(SIGTTIN, "Stopped (tty input)");
240 #endif
241 #ifdef SIGTTOU
242 store_desc(SIGTTOU, "Stopped (tty output)");
243 #endif
244 #ifdef SIGVTALRM
245 store_desc(SIGVTALRM, "virtual timer expired");
246 #endif
247 #ifdef SIGPROF
248 store_desc(SIGPROF, "profiling timer expired");
249 #endif
250 #ifdef SIGXCPU
251 store_desc(SIGXCPU, "exceeded cpu limit");
252 #endif
253 #ifdef SIGXFSZ
254 store_desc(SIGXFSZ, "exceeded file size limit");
255 #endif
256
257 for (sig = 0; sig < APR_NUMSIG; ++sig)
258 if (signal_description[sig] == NULL)
259 signal_description[sig] = apr_psprintf(pglobal, "signal #%d", sig);
260 }
261
262 const char *apr_signal_description_get(int signum)
263 {
264 return
265 (signum >= 0 && signum < APR_NUMSIG)
266 ? signal_description[signum]
267 : "unknown signal (number)";
268 }
269
270 #endif /* SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST */
271
272 #if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2)
273
274 static void remove_sync_sigs(sigset_t *sig_mask)
275 {
276 #ifdef SIGABRT
277 sigdelset(sig_mask, SIGABRT);
278 #endif
279 #ifdef SIGBUS
280 sigdelset(sig_mask, SIGBUS);
281 #endif
282 #ifdef SIGEMT
283 sigdelset(sig_mask, SIGEMT);
284 #endif
285 #ifdef SIGFPE
286 sigdelset(sig_mask, SIGFPE);
287 #endif
288 #ifdef SIGILL
289 sigdelset(sig_mask, SIGILL);
290 #endif
291 #ifdef SIGIOT
292 sigdelset(sig_mask, SIGIOT);
293 #endif
294 #ifdef SIGPIPE
295 sigdelset(sig_mask, SIGPIPE);
296 #endif
297 #ifdef SIGSEGV
298 sigdelset(sig_mask, SIGSEGV);
299 #endif
300 #ifdef SIGSYS
301 sigdelset(sig_mask, SIGSYS);
302 #endif
303 #ifdef SIGTRAP
304 sigdelset(sig_mask, SIGTRAP);
305 #endif
306
307 /* the rest of the signals removed from the mask in this function
308 * absolutely must be removed; you cannot block synchronous signals
309 * (requirement of pthreads API)
310 */
311 }
312
313 APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum))
314 {
315 sigset_t sig_mask;
316 #if APR_HAVE_SIGWAIT
317 int (*sig_func)(int signum) = (int (*)(int))signal_handler;
318 #endif
319
320 /* This thread will be the one responsible for handling signals */
321 sigfillset(&sig_mask);
322
323 /* On certain platforms, sigwait() returns EINVAL if any of various
324 * unblockable signals are included in the mask. This was first
325 * observed on AIX and Tru64.
326 */
327 #ifdef SIGKILL
328 sigdelset(&sig_mask, SIGKILL);
329 #endif
330 #ifdef SIGSTOP
331 sigdelset(&sig_mask, SIGSTOP);
332 #endif
333 #ifdef SIGCONT
334 sigdelset(&sig_mask, SIGCONT);
335 #endif
336 #ifdef SIGWAITING
337 sigdelset(&sig_mask, SIGWAITING);
338 #endif
339
340 /* no synchronous signals should be in the mask passed to sigwait() */
341 remove_sync_sigs(&sig_mask);
342
343 /* On AIX (4.3.3, at least), sigwait() won't wake up if the high-
344 * order bit of the second word of flags is turned on. sigdelset()
345 * returns an error when trying to turn this off, so we'll turn it
346 * off manually.
347 *
348 * Note that the private fields differ between 32-bit and 64-bit
349 * and even between _ALL_SOURCE and !_ALL_SOURCE. Except that on
350 * AIX 4.3 32-bit builds and 64-bit builds use the same definition.
351 *
352 * Applicable AIX fixes such that this is no longer needed:
353 *
354 * APAR IY23096 for AIX 51B, fix included in AIX 51C, and
355 * APAR IY24162 for 43X.
356 */
357 #if defined(_AIX)
358 #if defined(__64BIT__) && defined(_AIXVERSION_510)
359 #ifdef _ALL_SOURCE
360 sig_mask.ss_set[3] &= 0x7FFFFFFF;
361 #else /* not _ALL_SOURCE */
362 sig_mask.__ss_set[3] &= 0x7FFFFFFF;
363 #endif
364 #else /* not 64-bit build, or 64-bit build on 4.3 */
365 #ifdef _ALL_SOURCE
366 sig_mask.hisigs &= 0x7FFFFFFF;
367 #else /* not _ALL_SOURCE */
368 sig_mask.__hisigs &= 0x7FFFFFFF;
369 #endif
370 #endif
371 #endif /* _AIX */
372
373 while (1) {
374 #if APR_HAVE_SIGWAIT
375 int signal_received;
376
377 if (apr_sigwait(&sig_mask, &signal_received) != 0)
378 {
379 /* handle sigwait() error here */
380 }
381
382 if (sig_func(signal_received) == 1) {
383 return APR_SUCCESS;
384 }
385 #elif HAVE_SIGSUSPEND
386 sigsuspend(&sig_mask);
387 #else
388 #error No apr_sigwait() and no sigsuspend()
389 #endif
390 }
391 }
392
393 APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
394 {
395 sigset_t sig_mask;
396 int rv;
397
398 /* All threads should mask out signals to be handled by
399 * the thread doing sigwait().
400 *
401 * No thread should ever block synchronous signals.
402 * See the Solaris man page for pthread_sigmask() for
403 * some information. Solaris chooses to knock out such
404 * processes when a blocked synchronous signal is
405 * delivered, skipping any registered signal handler.
406 * AIX doesn't call a signal handler either. At least
407 * one level of linux+glibc does call the handler even
408 * when the synchronous signal is blocked.
409 */
410 sigfillset(&sig_mask);
411 remove_sync_sigs(&sig_mask);
412
413 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
414 if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
415 rv = errno;
416 }
417 #else
418 if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
419 #ifdef HAVE_ZOS_PTHREADS
420 rv = errno;
421 #endif
422 }
423 #endif
424 return rv;
425 }
426
427 #endif /* APR_HAS_THREADS && ... */
428
429 APR_DECLARE(apr_status_t) apr_signal_block(int signum)
430 {
431 #if APR_HAVE_SIGACTION
432 sigset_t sig_mask;
433 int rv;
434
435 sigemptyset(&sig_mask);
436
437 sigaddset(&sig_mask, signum);
438
439 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
440 if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
441 rv = errno;
442 }
443 #else
444 if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
445 #ifdef HAVE_ZOS_PTHREADS
446 rv = errno;
447 #endif
448 }
449 #endif
450 return rv;
451 #else
452 return APR_ENOTIMPL;
453 #endif
454 }
455
456 APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
457 {
458 #if APR_HAVE_SIGACTION
459 sigset_t sig_mask;
460 int rv;
461
462 sigemptyset(&sig_mask);
463
464 sigaddset(&sig_mask, signum);
465
466 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
467 if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
468 rv = errno;
469 }
470 #else
471 if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
472 #ifdef HAVE_ZOS_PTHREADS
473 rv = errno;
474 #endif
475 }
476 #endif
477 return rv;
478 #else
479 return APR_ENOTIMPL;
480 #endif
481 }