1.0.5.4: signal handler consing causing GCs
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 29 Apr 2007 15:51:01 +0000 (15:51 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 29 Apr 2007 15:51:01 +0000 (15:51 +0000)
 * Skip GC attempt if interrupts are enabled but GC signals are
   blocked in the context we would restore.

   This can happen at least when a signal handler conses while GC
   signals are blocked, so what we take a PendingInterrupt trap while
   in the original handler.

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

diff --git a/NEWS b/NEWS
index ca11a2a..bf72037 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
 changes in sbcl-1.0.6 relative to sbcl-1.0.5:
   * bug fix: GETHASH, (SETF GETHASH), CLRHASH and REMHASH are now
     interrupt safe.
+  * bug fix: GC race condition occasionally resulting in crashes with
+    the error message "SIG_STOP_FOR_GC blocked at a bad place" has been
+    fixed.
 
 changes in sbcl-1.0.5 relative to sbcl-1.0.4:
   * incompatible change: removed writer methods for host-ent-name,
index 4182448..02321c2 100644 (file)
@@ -2468,8 +2468,17 @@ maybe_gc(os_context_t *context)
      */
 #ifndef LISP_FEATURE_WIN32
     if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) {
-        thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
-        check_gc_signals_unblocked_or_lose();
+        sigset_t *context_sigmask = os_context_sigmask_addr(context);
+        /* What if the context we'd like to restore has GC signals
+         * blocked? Just skip the GC: we can't set GC_PENDING, because
+         * that would block the next attempt, and we don't know when
+         * we'd next check for it -- and it's hard to be sure that
+         * unblocking would be safe. */
+        if (sigismember(context_sigmask,SIG_STOP_FOR_GC)) {
+            undo_fake_foreign_function_call(context);
+            return 1;
+        }
+        thread_sigmask(SIG_SETMASK, context_sigmask, 0);
     }
     else
         unblock_gc_signals();
index 20dfab2..08aba57 100644 (file)
@@ -136,27 +136,6 @@ check_blockables_blocked_or_lose(void)
 }
 
 void
-check_gc_signals_unblocked_or_lose(void)
-{
-#ifdef LISP_FEATURE_SB_THREAD
-# if !defined(LISP_FEATURE_WIN32)
-    /* Get the current sigmask, by blocking the empty set. */
-    sigset_t empty,current;
-    sigemptyset(&empty);
-    thread_sigmask(SIG_BLOCK, &empty, &current);
-    if (sigismember(&current, SIG_STOP_FOR_GC))
-        lose("SIG_STOP_FOR_GC blocked in thread %p at a bad place\n",
-             arch_os_get_current_thread());
-#  if defined(SIG_RESUME_FROM_GC)
-    if (sigismember(&current, SIG_RESUME_FROM_GC))
-        lose("SIG_RESUME_FROM_GC blocked in thread %p at a bad place\n",
-             arch_os_get_current_thread());
-#  endif
-# endif
-#endif
-}
-
-void
 unblock_gc_signals(void)
 {
 #ifdef LISP_FEATURE_SB_THREAD
index 729077b..3da9d7f 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".)
-"1.0.5.3"
+"1.0.5.4"