From: normalperson@... Date: 2014-11-24T21:08:31+00:00 Subject: [ruby-core:66442] [ruby-trunk - Bug #10540] Yielded fibers do not execute ensure blocks Issue #10540 has been updated by Eric Wong. This seems unfortunate. I'm not sure if there's a good way to do this automatically with current APIs because Fibers require explicit scheduling. Perhaps storing Fibers in Thread.current and having a terminate_all_fibers method can be helpful: Thread.new do begin do_something_which_creates_fibers ensure # all thread-local fibers are resumed until they're dead terminate_all_fibers end end ---------------------------------------- Bug #10540: Yielded fibers do not execute ensure blocks https://bugs.ruby-lang.org/issues/10540#change-50069 * Author: Yehuda Katz * Status: Open * Priority: Normal * Assignee: * Category: * Target version: * ruby -v: ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN ---------------------------------------- When a thread has paused fibers, if an exception occurs anywhere in the thread, `ensure` blocks in the paused fibers do not execute. The effect of this is that block-scoped resources (like File.open, Mutex#synchronize, ActiveRecord transactions) can easily leak due to non-local effects. This may result in strange effects, like checking connections back into a connection pool that are in the wrong state, where the correct state was guarded with an `ensure` block. Here is a very simple repro of this situation: ~~~ Thread.new { Fiber.new { begin puts "YIELD" Fiber.yield ensure puts "UNWIND" end }.resume raise } ~~~ Expected result: `YIELD` is printed, followed by `UNWIND` Actual result: `YIELD` is printed, but `UNWIND` is never printed -- https://bugs.ruby-lang.org/