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... :-/
/* ---------------------------------------------------------------------------
/* ---------------------------------------------------------------------------
- * $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
*
*
* (c) The GHC Team, 1998-2003
*
- IF_DEBUG(scheduler, printAllThreads());
+// IF_DEBUG(scheduler, printAllThreads());
#if defined(RTS_SUPPORTS_THREADS)
// Yield the capability to higher-priority tasks if necessary.
#if defined(RTS_SUPPORTS_THREADS)
// Yield the capability to higher-priority tasks if necessary.
/* Run the current thread
*/
prev_what_next = t->what_next;
/* Run the current thread
*/
prev_what_next = t->what_next;
+
+ errno = t->saved_errno;
+
switch (prev_what_next) {
switch (prev_what_next) {
case ThreadKilled:
case ThreadComplete:
/* Thread already finished, return to scheduler. */
ret = ThreadFinished;
break;
case ThreadKilled:
case ThreadComplete:
/* Thread already finished, return to scheduler. */
ret = ThreadFinished;
break;
- errno = t->saved_errno;
ret = StgRun((StgFunPtr) stg_returnToStackTop, &cap->r);
ret = StgRun((StgFunPtr) stg_returnToStackTop, &cap->r);
- t->saved_errno = errno;
case ThreadInterpret:
ret = interpretBCO(cap);
break;
case ThreadInterpret:
ret = interpretBCO(cap);
break;
default:
barf("schedule: invalid what_next field");
}
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 */
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* Costs for the scheduler are assigned to CCS_SYSTEM */
#elif !defined(GRAN) && !defined(PAR)
IF_DEBUG(scheduler,fprintf(stderr,"sched: "););
#endif
#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
#if defined(PAR)
/* HACK 675: if the last thread didn't yield, make sure to print a