From 28e69a6b23d437997d8963dd14a3fc9a5f292700 Mon Sep 17 00:00:00 2001 From: simonmar Date: Wed, 25 Sep 2002 14:46:34 +0000 Subject: [PATCH] [project @ 2002-09-25 14:46:31 by simonmar] Fix a scheduling/GC bug, spotted by Wolfgang Thaller. If a main thread completes, and a GC runs before the return (from rts_evalIO()) happens, then the thread might be GC'd before we get a chance to extract its return value, leading to barf("main thread has been GC'd") from the garbage collector. The fix is to treat all main threads which have completed as roots: this is logically the right thing to do, because these threads must be retained by virtue of holding the return value, and this is a property of main threads only. --- ghc/rts/GC.c | 17 ++++++++++------- ghc/rts/Schedule.c | 21 ++++++++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index c0e1a4a..853d548 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: GC.c,v 1.143 2002/09/18 06:34:07 mthomas Exp $ + * $Id: GC.c,v 1.144 2002/09/25 14:46:34 simonmar Exp $ * * (c) The GHC Team 1998-1999 * @@ -1306,14 +1306,17 @@ isAlive(StgClosure *p) if (LOOKS_LIKE_STATIC(p) || bd->gen_no > N) { return p; } - // large objects have an evacuated flag + + // if it's a pointer into to-space, then we're done + if (bd->flags & BF_EVACUATED) { + return p; + } + + // large objects use the evacuated flag if (bd->flags & BF_LARGE) { - if (bd->flags & BF_EVACUATED) { - return p; - } else { - return NULL; - } + return NULL; } + // check the mark bit for compacted steps if (bd->step->is_compacted && is_marked((P_)p,bd)) { return p; diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index 6973954..9759b55 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -1,5 +1,5 @@ /* --------------------------------------------------------------------------- - * $Id: Schedule.c,v 1.155 2002/09/18 06:34:07 mthomas Exp $ + * $Id: Schedule.c,v 1.156 2002/09/25 14:46:31 simonmar Exp $ * * (c) The GHC Team, 1998-2000 * @@ -2477,6 +2477,25 @@ GetRoots(evac_fn evac) // mark the signal handlers (signals should be already blocked) markSignalHandlers(evac); #endif + + // main threads which have completed need to be retained until they + // are dealt with in the main scheduler loop. They won't be + // retained any other way: the GC will drop them from the + // all_threads list, so we have to be careful to treat them as roots + // here. + { + StgMainThread *m; + for (m = main_threads; m != NULL; m = m->link) { + switch (m->tso->what_next) { + case ThreadComplete: + case ThreadKilled: + evac((StgClosure **)&m->tso); + break; + default: + break; + } + } + } } /* ----------------------------------------------------------------------------- -- 1.7.10.4