boundTaskExiting: don't set task->stopped unless this is the last call (#4850)
authorSimon Marlow <marlowsd@gmail.com>
Tue, 21 Dec 2010 11:58:07 +0000 (11:58 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Tue, 21 Dec 2010 11:58:07 +0000 (11:58 +0000)
commit9201a2d104103c2271a03d035555d2bef8a625bb
tree5ea94e8bccd0f25f20cd7c26a480d98e26e6fedf
parentd8334d807812e40f67770ffc37608c0ce66f96b2
boundTaskExiting: don't set task->stopped unless this is the last call (#4850)
The bug in this case was that we had a worker thread making a foreign
call which invoked a callback (in this case it was performGC, I
think).  When the callback ended, boundTaskExiting() was setting
task->stopped, but the Task is now per-OS-thread, so it is shared by
the worker that made the original foreign call.  When the foreign call
returned, because task->stopped was set, the worker was not placed on
the queue of spare workers.  Somehow the worker woke up again, and
found the spare_workers queue empty, which lead to a crash.

Two bugs here: task->stopped should not have been set by
boundTaskExiting (this broke when I split the Task and InCall structs,
in 6.12.2), and releaseCapabilityAndQueueWorker() should not be
testing task->stopped anyway, because it should only ever be called
when task->stopped is false (this is now an assertion).
rts/Task.c