do_checks: do not set HpAlloc if the stack check fails
authorSimon Marlow <marlowsd@gmail.com>
Thu, 25 Mar 2010 11:03:28 +0000 (11:03 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 25 Mar 2010 11:03:28 +0000 (11:03 +0000)
commit5c3ea9fb995233c31163d65bee64ab1dca663df4
tree393573c3b44f28fc478d8829eb4ff50fb2fe4e96
parent813f208a7c04bc740a43cb29ee248b9599415b40
do_checks: do not set HpAlloc if the stack check fails

This fixes a very rare heap corruption bug, whereby

 - a context switch is requested, which sets HpLim to zero
   (contextSwitchCapability(), called by the timer signal or
   another Capability).

 - simultaneously a stack check fails, in a code fragment that has
   both a stack and a heap check.

The RTS then assumes that a heap-check failure has occurred and
subtracts HpAlloc from Hp, although in fact it was a stack-check
failure and retreating Hp will overwrite valid heap objects.  The bug
is that HpAlloc should only be set when Hp has been incremented by the
heap check.  See comments in rts/HeapStackCheck.cmm for more details.

This bug is probably incredibly rare in practice, but I happened to be
working on a test that triggers it reliably:
concurrent/should_run/throwto001, compiled with -O -threaded, args 30
300 +RTS -N2, run repeatedly in a loop.
compiler/codeGen/CgHeapery.lhs