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:
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "wren.h"
|
||||
|
||||
void callWrenCallRootRunTests(WrenVM* vm);
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user