fix: abort all fibers along call chain when one fiber errors
In runtimeError, walk the entire fiber call chain and set each fiber's error field to the same error value, unhooking callers as we go. Previously only the immediate caller was considered, leaving intermediate fibers in an inconsistent state. This ensures that when a fiber aborts, every fiber in the chain up to (but not including) the one that catches the error via try() is properly marked as errored. Also remove the old nested fiber tests from try.wren and add a new comprehensive test (try_through_call.wren) that verifies the percolation behavior through multiple levels of fiber calls and confirms that intermediate fibers carry the error while the catching fiber and its callers remain clean.
This commit is contained in:
@@ -8,34 +8,3 @@ System.print(fiber.try())
|
||||
// expect: before
|
||||
// expect: Bool does not implement 'unknownMethod'.
|
||||
System.print("after try") // expect: after try
|
||||
|
||||
var fiber2 = Fiber.new {
|
||||
var fiberInner = Fiber.new {
|
||||
System.print("before")
|
||||
true.unknownMethod
|
||||
System.print("after")
|
||||
}
|
||||
fiberInner.call()
|
||||
}
|
||||
|
||||
System.print(fiber2.try())
|
||||
// expect: before
|
||||
// expect: Bool does not implement 'unknownMethod'.
|
||||
System.print("after try") // expect: after try
|
||||
|
||||
var fiber3 = Fiber.new {
|
||||
var fiberInner = Fiber.new {
|
||||
var fiberInnerInner = Fiber.new {
|
||||
System.print("before")
|
||||
true.unknownMethod
|
||||
System.print("after")
|
||||
}
|
||||
fiberInnerInner.call()
|
||||
}
|
||||
fiberInner.call()
|
||||
}
|
||||
|
||||
System.print(fiber3.try())
|
||||
// expect: before
|
||||
// expect: Bool does not implement 'unknownMethod'.
|
||||
System.print("after try") // expect: after try
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// A runtime error percolates through the fiber call chain until it hits a
|
||||
// try(). Every intermediate fiber is aborted too.
|
||||
|
||||
var fiber1 = Fiber.new {
|
||||
System.print("1 before")
|
||||
Fiber.abort("Abort!")
|
||||
System.print("1 after")
|
||||
}
|
||||
|
||||
var fiber2 = Fiber.new {
|
||||
System.print("2 before")
|
||||
fiber1.call()
|
||||
System.print("2 after")
|
||||
}
|
||||
|
||||
var fiber3 = Fiber.new {
|
||||
System.print("3 before")
|
||||
fiber2.call()
|
||||
System.print("3 after")
|
||||
}
|
||||
|
||||
var fiber4 = Fiber.new {
|
||||
System.print("4 before")
|
||||
fiber3.try()
|
||||
System.print("4 after")
|
||||
}
|
||||
|
||||
var fiber5 = Fiber.new {
|
||||
System.print("5 before")
|
||||
fiber4.call()
|
||||
System.print("5 after")
|
||||
}
|
||||
|
||||
fiber5.call()
|
||||
// expect: 5 before
|
||||
// expect: 4 before
|
||||
// expect: 3 before
|
||||
// expect: 2 before
|
||||
// expect: 1 before
|
||||
// expect: 4 after
|
||||
// expect: 5 after
|
||||
System.print("after") // expect: after
|
||||
|
||||
// The fibers between the aborted one and the tried one are all errored.
|
||||
System.print(fiber1.error) // expect: Abort!
|
||||
System.print(fiber2.error) // expect: Abort!
|
||||
System.print(fiber3.error) // expect: Abort!
|
||||
System.print(fiber4.error) // expect: null
|
||||
System.print(fiber5.error) // expect: null
|
||||
Reference in New Issue
Block a user