diff options
-rw-r--r-- | CHANGES | 10 | ||||
-rw-r--r-- | threadproc/unix/signals.c | 49 |
2 files changed, 56 insertions, 3 deletions
@@ -1,7 +1,13 @@ Changes with APR b1 - *) change the apr_table_elts macro so that it provides access via - a const pointer instead of a non-const pointer + *) 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. + [Jeff Trawick] + + *) Change the apr_table_elts macro so that it provides access via + a const pointer instead of a non-const pointer. [Brian Pane <bpane@pacbell.net] *) Use strerror_r() where available, since strerror() isn't always 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); |