Closed jpco closed 8 months ago
Okay, I tried a globalroot
fix and it confirmed that's where the bug is. Unfortunately doing that is itself buggy as illustrated in the following scenario:
./es -c 'set-foo = @ {if {~ $* ()} {catch @ {result ()} {throw error set-foo YIKES}}}; local (foo = !) {throw whatever}'
YIKES
Using a simple globalroot
causes the second throw in set-foo
to clobber the exception from the first throw whatever
, which means that the catcher in $&batchloop
sees the exception error set-foo YIKES
, when it should see the exception whatever
. Not great.
Minimal repro: compile with
-DGCDEBUG=1
and runIt seems the problem is that if a GC is triggered within in the call chain of
throw(e)
->varpop(foo)
->callsettor(foo, NULL)
->append(set-foo, NULL)
->gcreserve()
, thene
becomes invalid memory by the time it's being used in aCatchException
block. This implies there's a missing root fore
somewhere.Unfortunately, because
throw
hacks up the root list, it's tricky to try to roote
in the stack there. I wonder if there's someglobalroot
-related workaround that's possible. Or maybee
needs to be rooted inhandler->rootlist
before calling thevarpop()
s? That seems a little wacky.