From d9d75ffc2f436767c81a4091ec4ff7006c1ec676 Mon Sep 17 00:00:00 2001 From: Gabor Melis Date: Mon, 16 Feb 2009 22:01:45 +0000 Subject: [PATCH] 1.0.25.38: fix maybe_gc --- src/runtime/gc-common.c | 25 +++++++++++++------------ src/runtime/interrupt.c | 36 +++++++++++++++++++++++++++--------- src/runtime/interrupt.h | 1 + version.lisp-expr | 2 +- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index 0da8a1f..d01a4fc 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -2440,10 +2440,8 @@ maybe_gc(os_context_t *context) FSHOW((stderr, "/maybe_gc: calling SUB_GC\n")); /* FIXME: Nothing must go wrong during GC else we end up running * the debugger, error handlers, and user code in general in a - * potentially unsafe place. With deferrables blocked due to - * fake_foreign_function_call + unblock_gc_signals(), we'll not - * have a pleasant time either. Running out of the control stack - * or the heap in SUB-GC are ways to lose. Of course, deferrables + * potentially unsafe place. Running out of the control stack or + * the heap in SUB-GC are ways to lose. Of course, deferrables * cannot be unblocked because there may be a pending handler, or * we may even be in a WITHOUT-INTERRUPTS. */ gc_happened = funcall0(StaticSymbolFunction(SUB_GC)); @@ -2452,16 +2450,19 @@ maybe_gc(os_context_t *context) if ((gc_happened != NIL) && /* See if interrupts are enabled or it's possible to enable * them. POST-GC has a similar check, but we don't want to - * unlock deferrables in that case, because if there is a - * pending interrupt we'd lose, but more to point the POST-GC - * runs user code in a pretty much arbitrary place so it - * better not be in WITHOUT-INTERRUPTS. */ + * unlock deferrables in that case and get a pending interrupt + * here. */ ((SymbolValue(INTERRUPTS_ENABLED,thread) != NIL) || (SymbolValue(ALLOW_WITH_INTERRUPTS,thread) != NIL))) { - FSHOW((stderr, "/maybe_gc: calling POST_GC\n")); - if (!interrupt_handler_pending_p()) - unblock_deferrable_signals(); - funcall0(StaticSymbolFunction(POST_GC)); + sigset_t *context_sigmask = os_context_sigmask_addr(context); + if (!deferrables_blocked_in_sigset_p(context_sigmask)) { + FSHOW((stderr, "/maybe_gc: calling POST_GC\n")); + thread_sigmask(SIG_SETMASK, context_sigmask, 0); + check_gc_signals_unblocked_or_lose(); + funcall0(StaticSymbolFunction(POST_GC)); + } else { + FSHOW((stderr, "/maybe_gc: punting on POST_GC due to blockage\n")); + } } undo_fake_foreign_function_call(context); FSHOW((stderr, "/maybe_gc: returning\n")); diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index 78f34fb..22ea827 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -164,6 +164,19 @@ sigset_t blockable_sigset; sigset_t gc_sigset; #endif +boolean +deferrables_blocked_in_sigset_p(sigset_t *sigset) +{ +#if !defined(LISP_FEATURE_WIN32) + int i; + for(i = 1; i < NSIG; i++) { + if (sigismember(&deferrable_sigset, i) && sigismember(sigset, i)) + return 1; + } +#endif + return 0; +} + void check_deferrables_unblocked_in_sigset_or_lose(sigset_t *sigset) { @@ -669,24 +682,24 @@ interrupt_handle_pending(os_context_t *context) check_blockables_blocked_or_lose(); - /* If GC/SIG_STOP_FOR_GC stroke during PA and there was no pending + /* If GC/SIG_STOP_FOR_GC struck during PA and there was no pending * handler, then the pending mask was saved and * gc_blocked_deferrables set. Hence, there can be no pending * handler and it's safe to restore the pending mask. * * Note, that if gc_blocked_deferrables is false we may still have - * to GC. In this case, we are coming out of a WITHOUT-GCING. */ + * to GC. In this case, we are coming out of a WITHOUT-GCING or a + * pseudo atomic was interrupt be a deferrable first. */ if (data->gc_blocked_deferrables) { if (data->pending_handler) lose("GC blocked deferrables but still got a pending handler."); if (SymbolValue(GC_INHIBIT,thread)!=NIL) lose("GC blocked deferrables while GC is inhibited."); - /* restore the saved signal mask from the original signal - * (the one that interrupted us during the critical - * section) into the os_context for the signal we're - * currently in the handler for. This should ensure that - * when we return from the handler the blocked signals are - * unblocked */ + /* Restore the saved signal mask from the original signal (the + * one that interrupted us during the critical section) into + * the os_context for the signal we're currently in the + * handler for. This should ensure that when we return from + * the handler the blocked signals are unblocked. */ sigcopyset(os_context_sigmask_addr(context), &data->pending_mask); data->gc_blocked_deferrables = 0; } @@ -706,6 +719,7 @@ interrupt_handle_pending(os_context_t *context) * is used in SUB-GC as part of the mechanism to supress * recursive gcs.*/ if (SymbolValue(GC_PENDING,thread) == T) { + /* Two reasons for doing this. First, if there is a * pending handler we don't want to run. Second, we are * going to clear pseudo atomic interrupted to avoid @@ -722,7 +736,11 @@ interrupt_handle_pending(os_context_t *context) /* GC_PENDING is cleared in SUB-GC, or if another thread * is doing a gc already we will get a SIG_STOP_FOR_GC and - * that will clear it. */ + * that will clear it. + * + * If there is a pending handler or gc was triggerred in a + * signal handler then maybe_gc won't run POST_GC and will + * return normally. */ if (!maybe_gc(context)) lose("GC not inhibited but maybe_gc did not GC."); diff --git a/src/runtime/interrupt.h b/src/runtime/interrupt.h index 1a4c2af..325723f 100644 --- a/src/runtime/interrupt.h +++ b/src/runtime/interrupt.h @@ -43,6 +43,7 @@ extern void unblock_deferrable_signals(void); extern void unblock_gc_signals(void); extern void unblock_signals_in_context_and_maybe_warn(os_context_t *context); +extern boolean deferrables_blocked_in_sigset_p(sigset_t *sigset); extern void check_deferrables_blocked_or_lose(void); extern void check_blockables_blocked_or_lose(void); extern void check_gc_signals_unblocked_or_lose(void); diff --git a/version.lisp-expr b/version.lisp-expr index 76c2dbc..4ece006 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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.25.37" +"1.0.25.38" -- 1.7.10.4