diff options
author | Jeff Trawick <trawick@apache.org> | 2001-11-12 19:47:31 +0000 |
---|---|---|
committer | Jeff Trawick <trawick@apache.org> | 2001-11-12 19:47:31 +0000 |
commit | 4b883856c3b51a07eda1e3782bf6f55cf3720770 (patch) | |
tree | f460ff965c70a271d125a18efec4761b933ef821 /threadproc/unix | |
parent | 13a44a3eb45dfd95bfc5b22b6a0ca821c75fb29b (diff) | |
download | apr-4b883856c3b51a07eda1e3782bf6f55cf3720770.tar.gz apr-4b883856c3b51a07eda1e3782bf6f55cf3720770.zip |
Fix apr_setup_signal_thread() so that threads don't block
synchronous signals (e.g., SIGSEGV). It is a programming error
to do so, and some platforms (e.g., Solaris, AIX) don't call any
registered signal handler when such signals are blocked.
Thanks are due to Dick Dunbar <RLDunbar@pacbell.net>, who pointed
this out to me in the context of debugging a threaded module for
Apache 1.3.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@62509 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'threadproc/unix')
-rw-r--r-- | threadproc/unix/signals.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/threadproc/unix/signals.c b/threadproc/unix/signals.c index 0872ecc4a..6d49cc218 100644 --- a/threadproc/unix/signals.c +++ b/threadproc/unix/signals.c @@ -268,6 +268,41 @@ const char *apr_signal_get_description(int signum) #endif /* SYS_SIGLIST_DECLARED */ #if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2) + +static void remove_sync_sigs(sigset_t *sig_mask) +{ +#ifdef SIGABRT + sigdelset(sig_mask, SIGABRT); +#endif +#ifdef SIGBUS + sigdelset(sig_mask, SIGBUS); +#endif +#ifdef SIGEMT + sigdelset(sig_mask, SIGEMT); +#endif +#ifdef SIGFPE + sigdelset(sig_mask, SIGFPE); +#endif +#ifdef SIGILL + sigdelset(sig_mask, SIGILL); +#endif +#ifdef SIGIOT + sigdelset(sig_mask, SIGIOT); +#endif +#ifdef SIGPIPE + sigdelset(sig_mask, SIGPIPE); +#endif +#ifdef SIGSEGV + sigdelset(sig_mask, SIGSEGV); +#endif +#ifdef SIGSYS + sigdelset(sig_mask, SIGSYS); +#endif +#ifdef SIGTRAP + sigdelset(sig_mask, SIGTRAP); +#endif +} + APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum)) { sigset_t sig_mask; @@ -329,8 +364,20 @@ APR_DECLARE(apr_status_t) apr_setup_signal_thread(void) sigset_t sig_mask; int rv; - /* All threads should mask signals out, according to sigwait(2) man page */ + /* All threads should mask out signals to be handled by + * the thread doing sigwait(). + * + * No thread should ever block synchronous signals. + * See the Solaris man page for pthread_sigmask() for + * some information. Solaris chooses to knock out such + * processes when a blocked synchronous signal is + * delivered, skipping any registered signal handler. + * AIX doesn't call a signal handler either. At least + * one level of linux+glibc does call the handler even + * when the synchronous signal is blocked. + */ sigfillset(&sig_mask); + remove_sync_sigs(&sig_mask); #if defined(SIGPROCMASK_SETS_THREAD_MASK) rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL); |