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:
Bob Nystrom
2017-10-06 14:39:00 +00:00
parent 85c4e9aa57
commit eecc18244f
3 changed files with 71 additions and 50 deletions
-31
View File
@@ -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
+49
View File
@@ -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