*/
#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);
+#ifdef LISP_FEATURE_SB_THREAD
+ /* 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.
+ *
+ * FIXME: This is not actually much better: we may already have
+ * GC_PENDING set, and presumably our caller assumes that we will
+ * clear it. Perhaps we should, even though we don't actually GC? */
+ if (sigismember(context_sigmask,SIG_STOP_FOR_GC)) {
+ undo_fake_foreign_function_call(context);
+ return 1;
+ }
+#endif
+ thread_sigmask(SIG_SETMASK, context_sigmask, 0);
}
else
unblock_gc_signals();
#endif
+ /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp:
+ * otherwise two threads racing here may deadlock: the other will
+ * wait on the GC lock, and the other cannot stop the first one... */
funcall0(SymbolFunction(SUB_GC));
undo_fake_foreign_function_call(context);
return 1;