Raising an exception on a thread that is in a Fiber causes a NullPointerException #1463
Seeing this periodically in an app that uses Fibers and timeout.rb. Timeout is raising exceptions on threads that are in a Fiber, which is crashing the fiber thread.
@headius was able to reproduce it via:
The text was updated successfully, but these errors were encountered:
In order to make a Thread and the fiber it is resuming look like a single unit, we must make sure that asynchronous exceptions happening at that boundary propagate the right direction. Exceptions raised in a thread waiting on Fiber#resume should go into the fiber and be handled there. Exceptions raised on a fiber waiting on Fiber.yield should go to the resuming thread and be handled there. This is done by capturing exceptions in Fiber#resume, transfer, and yield and propagating them to the waiting thread/fiber if its queue is still active. If that queue is not active (the fiber has exited), the exception is propagated upward in the current fiber/thread. The unknown case is what should happen to a fiber in which an exception (for example, a timeout) has triggered. In MRI, where there's really only one thread, the timeout would go to the resuming thread and happen arbitrarily in its running code. The originating fiber would be left undamaged as if nothing had happened, and would be subject to GC if abandoned or resumable as normal. In this patch, the original fiber performs the same exception-propagation loop and goes back to its queue for a resumed value; this should roughly match MRI's behavior. However, I am not sure I agree with MRI's behavior, or if MRI's behavior is correct, then Timeout should *never* be used around Fiber.yield, since it is impossible to know where and when it will fire.
This appears to be fixed now by 0c417d1.
There were two issues.
Both of these issues were fixed by the same modification to resume and yield. When a thread or fiber is waiting on another thread or fiber, exceptions it receives asynchronously need to be forwarded on to the target thread or fiber. Only if the target fiber is dead should the exception be propagated up the call stack as normal.
This issue illustrates more difficult issues with having fibers implemented using threads, but the fix seems to be working well and has so far been confirmed by @cheald. We'll call this fixed, but we should probably prioritize looking into alternative implementations of Fiber for JRuby 9k.
…available in 1.8 mode so the jrubyGH-1463 spec should just be skipped.