feat: prevent calling root fiber and refactor fiber state tracking

Add explicit check in `runFiber()` to reject calls to the root fiber, preventing VM crashes when a completed fiber's caller tries to resume it. Replace the boolean `callerIsTrying` field with a `FiberState` enum (`FIBER_TRY`, `FIBER_ROOT`, `FIBER_OTHER`) to track fiber invocation mode, updating all relevant primitives and initialization. Include new test cases (`call_root.wren`, `call_wren_call_root.*`) and re-entrancy documentation notes.
This commit is contained in:
Bob Nystrom
2018-07-21 17:02:29 +00:00
parent daeff98b83
commit 4b160f017b
11 changed files with 240 additions and 12 deletions
+29
View File
@@ -0,0 +1,29 @@
#include <stdio.h>
#include <string.h>
#include "wren.h"
#include "vm.h"
void callWrenCallRootRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "./test/api/call_wren_call_root", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(vm, 0);
WrenHandle* run = wrenMakeCallHandle(vm, "run()");
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, testClass);
WrenInterpretResult result = wrenCall(vm, run);
if (result == WREN_RESULT_RUNTIME_ERROR)
{
setExitCode(70);
}
else
{
printf("Missing runtime error.\n");
}
wrenReleaseHandle(vm, testClass);
wrenReleaseHandle(vm, run);
}
+3
View File
@@ -0,0 +1,3 @@
#include "wren.h"
void callWrenCallRootRunTests(WrenVM* vm);
+12
View File
@@ -0,0 +1,12 @@
class Test {
static run() {
var root = Fiber.current
System.print("begin root") // expect: begin root
Fiber.new {
System.print("in new fiber") // expect: in new fiber
root.call() // expect runtime error: Cannot call root fiber.
System.print("called root")
}.transfer()
}
}
+6 -1
View File
@@ -6,6 +6,7 @@
#include "benchmark.h"
#include "call.h"
#include "call_wren_call_root.h"
#include "error.h"
#include "get_variable.h"
#include "foreign_class.h"
@@ -101,6 +102,10 @@ static void afterLoad(WrenVM* vm)
{
callRunTests(vm);
}
else if (strstr(testName, "/call_wren_call_root.wren") != NULL)
{
callWrenCallRootRunTests(vm);
}
else if (strstr(testName, "/reset_stack_after_call_abort.wren") != NULL)
{
resetStackAfterCallAbortRunTests(vm);
@@ -122,5 +127,5 @@ int main(int argc, const char* argv[])
testName = argv[1];
setTestCallbacks(bindForeignMethod, bindForeignClass, afterLoad);
runFile(testName);
return 0;
return getExitCode();
}
+8
View File
@@ -0,0 +1,8 @@
var root = Fiber.current
System.print("begin root") // expect: begin root
Fiber.new {
System.print("in new fiber") // expect: in new fiber
root.call() // expect runtime error: Cannot call root fiber.
System.print("called root")
}.transfer()