0.9.8.12:
authorGabor Melis <mega@hotpop.com>
Thu, 5 Jan 2006 14:13:14 +0000 (14:13 +0000)
committerGabor Melis <mega@hotpop.com>
Thu, 5 Jan 2006 14:13:14 +0000 (14:13 +0000)
  * NetBSD has a different bug in SA_NODEFER, detect it (patch by
    Richard M Kreuter)

NEWS
src/runtime/interrupt.c
version.lisp-expr

diff --git a/NEWS b/NEWS
index a152d46..2aa55db 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ changes in sbcl-0.9.9 relative to sbcl-0.9.8:
     callbacks).  (thanks to Cyrus Harmon and Heiner Schwarte)
   * bug fix: allow non-simple string symbol names (reported by Paul
     Dietz)
+  * bug fix: interrupt handling on NetBSD (thanks to Richard M
+    Kreuter)
   * optimization: faster implementation of EQUAL
   * fixed segfaults on x86 FreeBSD 7-current (thanks to NIIMI Satoshi)
 
index 6a52053..eca23aa 100644 (file)
@@ -1080,9 +1080,17 @@ interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context)
  * the whole sa_mask is ignored and instead of not adding the signal
  * in question to the mask. That means if it's not blockable the
  * signal must be unblocked at the beginning of signal handlers.
+ *
+ * It turns out that NetBSD's SA_NODEFER doesn't DTRT in a different
+ * way: if SA_NODEFER is set and the signal is in sa_mask, the signal
+ * will be unblocked in the sigmask during the signal handler.  -- RMK
+ * X-mas day, 2005
  */
 static volatile int sigaction_nodefer_works = -1;
 
+#define SA_NODEFER_TEST_BLOCK_SIGNAL SIGABRT
+#define SA_NODEFER_TEST_KILL_SIGNAL SIGUSR1
+
 static void
 sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
 {
@@ -1090,8 +1098,14 @@ sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
     int i;
     sigemptyset(&empty);
     sigprocmask(SIG_BLOCK, &empty, &current);
+    /* There should be exactly two blocked signals: the two we added
+     * to sa_mask when setting up the handler.  NetBSD doesn't block
+     * the signal we're handling when SA_NODEFER is set; Linux before
+     * 2.6.13 or so also doesn't block the other signal when
+     * SA_NODEFER is set. */
     for(i = 1; i < NSIG; i++)
-        if (sigismember(&current, i) != ((i == SIGABRT) ? 1 : 0)) {
+        if (sigismember(&current, i) !=
+            (((i == SA_NODEFER_TEST_BLOCK_SIGNAL) || (i == signal)) ? 1 : 0)) {
             FSHOW_SIGNAL((stderr, "SA_NODEFER doesn't work, signal %d\n", i));
             sigaction_nodefer_works = 0;
         }
@@ -1107,19 +1121,23 @@ see_if_sigaction_nodefer_works()
     sa.sa_flags = SA_SIGINFO | SA_NODEFER;
     sa.sa_sigaction = sigaction_nodefer_test_handler;
     sigemptyset(&sa.sa_mask);
-    sigaddset(&sa.sa_mask, SIGABRT);
-    sigaction(SIGUSR1, &sa, &old_sa);
+    sigaddset(&sa.sa_mask, SA_NODEFER_TEST_BLOCK_SIGNAL);
+    sigaddset(&sa.sa_mask, SA_NODEFER_TEST_KILL_SIGNAL);
+    sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &sa, &old_sa);
     /* Make sure no signals are blocked. */
     {
         sigset_t empty;
         sigemptyset(&empty);
         sigprocmask(SIG_SETMASK, &empty, 0);
     }
-    kill(getpid(), SIGUSR1);
+    kill(getpid(), SA_NODEFER_TEST_KILL_SIGNAL);
     while (sigaction_nodefer_works == -1);
-    sigaction(SIGUSR1, &old_sa, NULL);
+    sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &old_sa, NULL);
 }
 
+#undef SA_NODEFER_TEST_BLOCK_SIGNAL
+#undef SA_NODEFER_TEST_KILL_SIGNAL
+
 static void
 unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
 {
index e6a68d3..d2f31b8 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.8.11"
+"0.9.8.12"