~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/threadproc/unix/signals.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
#ifdef 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
#ifdef 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 sys_siglist[signum];
 
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 < 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
 * SIGUSR2 is being removed from the mask for the convenience of
 
312
 * Purify users (Solaris, HP-UX, SGI) since Purify uses SIGUSR2
 
313
 */
 
314
#ifdef SIGUSR2
 
315
    sigdelset(sig_mask, SIGUSR2);
 
316
#endif
 
317
}
 
318
 
 
319
APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum))
 
320
{
 
321
    sigset_t sig_mask;
 
322
#if APR_HAVE_SIGWAIT
 
323
    int (*sig_func)(int signum) = (int (*)(int))signal_handler;
 
324
#endif
 
325
 
 
326
    /* This thread will be the one responsible for handling signals */
 
327
    sigfillset(&sig_mask);
 
328
 
 
329
    /* On certain platforms, sigwait() returns EINVAL if any of various
 
330
     * unblockable signals are included in the mask.  This was first 
 
331
     * observed on AIX and Tru64.
 
332
     */
 
333
#ifdef SIGKILL
 
334
    sigdelset(&sig_mask, SIGKILL);
 
335
#endif
 
336
#ifdef SIGSTOP
 
337
    sigdelset(&sig_mask, SIGSTOP);
 
338
#endif
 
339
#ifdef SIGCONT
 
340
    sigdelset(&sig_mask, SIGCONT);
 
341
#endif
 
342
#ifdef SIGWAITING
 
343
    sigdelset(&sig_mask, SIGWAITING);
 
344
#endif
 
345
 
 
346
    /* no synchronous signals should be in the mask passed to sigwait() */
 
347
    remove_sync_sigs(&sig_mask);
 
348
 
 
349
    /* On AIX (4.3.3, at least), sigwait() won't wake up if the high-
 
350
     * order bit of the second word of flags is turned on.  sigdelset()
 
351
     * returns an error when trying to turn this off, so we'll turn it
 
352
     * off manually.
 
353
     *
 
354
     * Note that the private fields differ between 32-bit and 64-bit
 
355
     * and even between _ALL_SOURCE and !_ALL_SOURCE.  Except that on
 
356
     * AIX 4.3 32-bit builds and 64-bit builds use the same definition.
 
357
     *
 
358
     * Applicable AIX fixes such that this is no longer needed:
 
359
     *
 
360
     * APAR IY23096 for AIX 51B, fix included in AIX 51C, and
 
361
     * APAR IY24162 for 43X.
 
362
     */
 
363
#if defined(_AIX)
 
364
#if defined(__64BIT__) && defined(_AIXVERSION_510)
 
365
#ifdef _ALL_SOURCE
 
366
        sig_mask.ss_set[3] &= 0x7FFFFFFF;
 
367
#else /* not _ALL_SOURCE */
 
368
        sig_mask.__ss_set[3] &= 0x7FFFFFFF;
 
369
#endif
 
370
#else /* not 64-bit build, or 64-bit build on 4.3 */
 
371
#ifdef _ALL_SOURCE
 
372
        sig_mask.hisigs &= 0x7FFFFFFF;
 
373
#else /* not _ALL_SOURCE */
 
374
        sig_mask.__hisigs &= 0x7FFFFFFF;
 
375
#endif
 
376
#endif
 
377
#endif /* _AIX */
 
378
 
 
379
    while (1) {
 
380
#if APR_HAVE_SIGWAIT
 
381
        int signal_received;
 
382
 
 
383
        if (apr_sigwait(&sig_mask, &signal_received) != 0)
 
384
        {
 
385
            /* handle sigwait() error here */
 
386
        }
 
387
        
 
388
        if (sig_func(signal_received) == 1) {
 
389
            return APR_SUCCESS;
 
390
        }
 
391
#elif HAVE_SIGSUSPEND
 
392
        sigsuspend(&sig_mask);
 
393
#else
 
394
#error No apr_sigwait() and no sigsuspend()
 
395
#endif
 
396
    }
 
397
}
 
398
 
 
399
APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
 
400
{
 
401
    sigset_t sig_mask;
 
402
    int rv;
 
403
 
 
404
    /* All threads should mask out signals to be handled by
 
405
     * the thread doing sigwait().
 
406
     *
 
407
     * No thread should ever block synchronous signals.
 
408
     * See the Solaris man page for pthread_sigmask() for
 
409
     * some information.  Solaris chooses to knock out such
 
410
     * processes when a blocked synchronous signal is 
 
411
     * delivered, skipping any registered signal handler.
 
412
     * AIX doesn't call a signal handler either.  At least
 
413
     * one level of linux+glibc does call the handler even
 
414
     * when the synchronous signal is blocked.
 
415
     */
 
416
    sigfillset(&sig_mask);
 
417
    remove_sync_sigs(&sig_mask);
 
418
 
 
419
#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
 
420
    if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
 
421
        rv = errno;
 
422
    }
 
423
#else
 
424
    if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
 
425
#ifdef PTHREAD_SETS_ERRNO
 
426
        rv = errno;
 
427
#endif
 
428
    }
 
429
#endif
 
430
    return rv;
 
431
}
 
432
 
 
433
#endif /* APR_HAS_THREADS && ... */
 
434
 
 
435
APR_DECLARE(apr_status_t) apr_signal_block(int signum)
 
436
{
 
437
#if APR_HAVE_SIGACTION
 
438
    sigset_t sig_mask;
 
439
    int rv;
 
440
 
 
441
    sigemptyset(&sig_mask);
 
442
 
 
443
    sigaddset(&sig_mask, signum);
 
444
 
 
445
#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
 
446
    if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
 
447
        rv = errno;
 
448
    }
 
449
#else
 
450
    if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
 
451
#ifdef PTHREAD_SETS_ERRNO
 
452
        rv = errno;
 
453
#endif
 
454
    }
 
455
#endif
 
456
    return rv;
 
457
#else
 
458
    return APR_ENOTIMPL;
 
459
#endif
 
460
}
 
461
 
 
462
APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
 
463
{
 
464
#if APR_HAVE_SIGACTION
 
465
    sigset_t sig_mask;
 
466
    int rv;
 
467
 
 
468
    sigemptyset(&sig_mask);
 
469
 
 
470
    sigaddset(&sig_mask, signum);
 
471
 
 
472
#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
 
473
    if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
 
474
        rv = errno;
 
475
    }
 
476
#else
 
477
    if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
 
478
#ifdef PTHREAD_SETS_ERRNO
 
479
        rv = errno;
 
480
#endif
 
481
    }
 
482
#endif
 
483
    return rv;
 
484
#else
 
485
    return APR_ENOTIMPL;
 
486
#endif
 
487
}