trawick 01/11/12 11:47:31
Modified: . CHANGES
threadproc/unix signals.c
Log:
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 <[EMAIL PROTECTED]>, who pointed
this out to me in the context of debugging a threaded module for
Apache 1.3.
Revision Changes Path
1.181 +8 -2 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.180
retrieving revision 1.181
diff -u -r1.180 -r1.181
--- CHANGES 2001/11/12 04:06:51 1.180
+++ CHANGES 2001/11/12 19:47:31 1.181
@@ -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 <[EMAIL PROTECTED]
*) Use strerror_r() where available, since strerror() isn't always
1.36 +48 -1 apr/threadproc/unix/signals.c
Index: signals.c
===================================================================
RCS file: /home/cvs/apr/threadproc/unix/signals.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- signals.c 2001/09/07 04:02:24 1.35
+++ signals.c 2001/11/12 19:47:31 1.36
@@ -268,6 +268,41 @@
#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 @@
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);