FiberIterator breaks normal exception handling
dgutov opened this issue · comments
Example (failing spec):
it "permits normal handling of errors" do
caught = nil
EM.synchrony do
begin
EM::Synchrony::FiberIterator.new(0..1, 2).each do |num|
raise "#{num} here"
end
rescue => e
caught = e.message
end
EM.stop
end
expect(caught).to eq("0 here")
end
The rescue
block is never entered, and the only way to catch the exception is with EM.error_handler
or catching it outside of the EM loop. Neither approach is composable.
@igrigorik Any ideas for an easy fix?
Right. But still, this kinda works (it outputs 3 at the end, at least):
counter = 0
EM.synchrony do
f = Fiber.current
maybe_stop = proc { f.resume if counter == 2 }
f1 = Fiber.new do
EM::Synchrony.sleep(1)
counter += 1
puts counter
maybe_stop[]
end
f2 = Fiber.new do
begin
EM::Synchrony.sleep(1)
counter += 1
puts counter
raise "aaa"
ensure
maybe_stop[]
end
end
EM.next_tick { f1.resume }
EM.next_tick { f2.resume }
begin
Fiber.yield
ensure
puts 3
end
EM.stop
end
And this catches the error, even though it was raised in a different fiber:
f = Fiber.new do
raise "bar"
end
begin
f.resume
rescue
puts "safety caught"
end
Maybe all worker fibers should be created by the caller fiber, on the main thread.
Alas, no. The second option doesn't seem like it'll work either when one of the worker fibers is suspended and then woken by the reactor thread (which is how we handle asynchrony normally).