From 86e487a2311303a82ac2936555ee08a285335caa Mon Sep 17 00:00:00 2001 From: simonmar Date: Thu, 27 May 2004 15:18:31 +0000 Subject: [PATCH] [project @ 2004-05-27 15:18:31 by simonmar] Fix a nasty bug: when saving errno in the TSO after running a thread, beware that the TSO might have moved, e.g. if the thread made a safe foreign call in the threaded RTS and a GC happened. We have to grab the new location of the TSO *before* saving errno. MERGE TO STABLE This was the most interesting bug hunt I've had in a while. The crash only showed up in about 1 in 4 runs of a program with 1000 Haskell threads, running on the threaded RTS. To make things worse, gdb doesn't support watchpoints in programs with multiple threads... :-/ --- ghc/rts/Schedule.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index e20eae2..9f5a7cc 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -1,5 +1,5 @@ /* --------------------------------------------------------------------------- - * $Id: Schedule.c,v 1.196 2004/05/06 12:20:04 wolfgang Exp $ + * $Id: Schedule.c,v 1.197 2004/05/27 15:18:31 simonmar Exp $ * * (c) The GHC Team, 1998-2003 * @@ -395,7 +395,7 @@ schedule( StgMainThread *mainThread USED_WHEN_RTS_SUPPORTS_THREADS, #endif - IF_DEBUG(scheduler, printAllThreads()); +// IF_DEBUG(scheduler, printAllThreads()); #if defined(RTS_SUPPORTS_THREADS) // Yield the capability to higher-priority tasks if necessary. @@ -897,23 +897,35 @@ run_thread: /* Run the current thread */ prev_what_next = t->what_next; + + errno = t->saved_errno; + switch (prev_what_next) { + case ThreadKilled: case ThreadComplete: /* Thread already finished, return to scheduler. */ ret = ThreadFinished; break; + case ThreadRunGHC: - errno = t->saved_errno; ret = StgRun((StgFunPtr) stg_returnToStackTop, &cap->r); - t->saved_errno = errno; break; + case ThreadInterpret: ret = interpretBCO(cap); break; + default: barf("schedule: invalid what_next field"); } + + // The TSO might have moved, so find the new location: + t = cap->r.rCurrentTSO; + + // And save the current errno in this thread. + t->saved_errno = errno; + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* Costs for the scheduler are assigned to CCS_SYSTEM */ @@ -929,7 +941,6 @@ run_thread: #elif !defined(GRAN) && !defined(PAR) IF_DEBUG(scheduler,fprintf(stderr,"sched: ");); #endif - t = cap->r.rCurrentTSO; #if defined(PAR) /* HACK 675: if the last thread didn't yield, make sure to print a -- 1.7.10.4