X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fsysmacs.lisp;h=b953cbcccfc3c678093f44e4f0774180c9d30b22;hb=8643c93d4db277f6e1cb880a42407ff29e19f618;hp=3556bc1c782440eeda9cf6da1af97b9da854a724;hpb=dcf8b8ccc1e15a5c1c6aba00204b7d3a81827acc;p=sbcl.git diff --git a/src/code/sysmacs.lisp b/src/code/sysmacs.lisp index 3556bc1..b953cbc 100644 --- a/src/code/sysmacs.lisp +++ b/src/code/sysmacs.lisp @@ -48,13 +48,30 @@ stopped for GC while T2 is waiting for the lock inside WITHOUT-GCING the system will be deadlocked. Since SBCL does not currently document its internal locks, application code can never be certain that this invariant is maintained." - `(unwind-protect - (without-interrupts - (let ((*gc-inhibit* t)) - ,@body)) - ;; the test is racy, but it can err only on the overeager side - (sb!kernel::maybe-handle-pending-gc))) - + (with-unique-names (without-gcing-body) + `(flet ((,without-gcing-body () + ,@body)) + (if *gc-inhibit* + (,without-gcing-body) + (without-interrupts + ;; We need to disable interrupts before disabling GC, so that + ;; signal handlers using locks don't accidentally try to grab + ;; them with GC inhibited. + ;; + ;; It would be nice to implement this with just a single UWP, but + ;; unfortunately it seems that it cannot be done: the naive + ;; solution of binding both *INTERRUPTS-ENABLED* and + ;; *GC-INHIBIT*, and checking for both pending GC and interrupts + ;; in the cleanup breaks if we have a GC pending, but no + ;; interrupts, and we receive an asynch unwind while checking for + ;; the pending GC: we unwind before handling the pending GC, and + ;; will be left running with further GCs blocked due to the GC + ;; pending flag. + (unwind-protect + (let ((*gc-inhibit* t)) + (,without-gcing-body)) + (when (or *gc-pending* #!+sb-thread *stop-for-gc-pending*) + (sb!unix::receive-pending-interrupt)))))))) ;;; EOF-OR-LOSE is a useful macro that handles EOF. (defmacro eof-or-lose (stream eof-error-p eof-value)