aboutsummaryrefslogtreecommitdiff
path: root/threadproc/unix
diff options
context:
space:
mode:
authorJeff Trawick <trawick@apache.org>2001-11-12 19:47:31 +0000
committerJeff Trawick <trawick@apache.org>2001-11-12 19:47:31 +0000
commit4b883856c3b51a07eda1e3782bf6f55cf3720770 (patch)
treef460ff965c70a271d125a18efec4761b933ef821 /threadproc/unix
parent13a44a3eb45dfd95bfc5b22b6a0ca821c75fb29b (diff)
downloadapr-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.c49
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);