From: "rmosolgo (Robert Mosolgo) via ruby-core" Date: 2023-12-28T15:57:52+00:00 Subject: [ruby-core:115966] [Ruby master Bug#20089] Fiber#kill transfers to root fiber Issue #20089 has been updated by rmosolgo (Robert Mosolgo). That definitely makes sense for a Fiber killing _itself_, but would you say that killing a _different_ Fiber should cause a fiber to transfer away? In my first script above, calling `worker.kill` causes the `manager` fiber to transfer. I looked a little deeper, it looks like this only happens when both Fibers have been started with `.transfer`. Here's a scenario with two different Fibers, one killing the other, and only the `.transfer`/`.transfer` case exits early: ```ruby puts "\n\nResume/Transfer" fiber1 = Fiber.new { puts "1. Fiber1 Runs" fiber2 = Fiber.new { puts "2. Fiber2 Runs" fiber1.transfer puts "Never: Fiber2 is killed" } fiber2.transfer fiber2.kill puts "3. Fiber1 finishes" } fiber1.resume puts "4. Exit" # Resume/Transfer # 1. Fiber1 Runs # 2. Fiber2 Runs # 3. Fiber1 finishes # 4. Exit puts "\n\nTransfer/Resume" fiber1 = Fiber.new { puts "1. Fiber1 Runs" fiber2 = Fiber.new { puts "2. Fiber2 Runs" Fiber.yield puts "Never: Fiber2 is killed" } fiber2.resume fiber2.kill puts "3. Fiber1 finishes" } fiber1.transfer puts "4. Exit" # Transfer/Resume # 1. Fiber1 Runs # 2. Fiber2 Runs # 3. Fiber1 finishes # 4. Exit puts "\n\nResume/Resume" fiber1 = Fiber.new { puts "1. Fiber1 Runs" fiber2 = Fiber.new { puts "2. Fiber2 Runs" Fiber.yield puts "Never: Fiber2 is killed" } fiber2.resume fiber2.kill puts "3. Fiber1 finishes" } fiber1.resume puts "4. Exit" # Resume/Resume # 1. Fiber1 Runs # 2. Fiber2 Runs # 3. Fiber1 finishes # 4. Exit puts "\n\nTransfer/Transfer" fiber1 = Fiber.new { puts "1. Fiber1 Runs" fiber2 = Fiber.new { puts "2. Fiber2 Runs" fiber1.transfer puts "Never: Fiber2 is killed" } fiber2.transfer fiber2.kill puts "3. Fiber1 finishes" } fiber1.transfer puts "4. Exit" # Transfer/Transfer # 1. Fiber1 Runs # 2. Fiber2 Runs # 4. Exit ``` Is there a more appropriate way to terminate `fiber2` in that case, while keeping control inside `fiber1`, or is this a bug? ---------------------------------------- Bug #20089: Fiber#kill transfers to root fiber https://bugs.ruby-lang.org/issues/20089#change-105925 * Author: rmosolgo (Robert Mosolgo) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I was hoping to use `Fiber#kill` to clean up formerly `.transfer`-d Fibers and work around https://bugs.ruby-lang.org/issues/20081, but I found that `Fiber#kill` has a similar control flow jump behavior. Is this on purpose, or a bug? Here's a script to test the behavior: ```ruby manager = Fiber.new do worker = Fiber.new do puts "2. Begin Worker" manager.transfer puts "This should never print -- killed" end puts "1. Transfer to Worker" worker.transfer puts "3. Killing Worker" worker.kill puts "4. Finished manager" end manager.transfer puts "5. Finished script" ``` I expected items `1` through `5` to be printed in order, but in fact, `4` is never printed: ``` $ ruby fiber_transfer_test.rb 1. Transfer to Worker 2. Begin Worker 3. Killing Worker 5. Finished script ``` It seems like `worker.kill` is transferring control to the top-level fiber instead of giving it back to `manager`. I also tried having the thread kill _itself_, hoping it would return to the fiber that originally `.transfer`ed to it, but it also seems to jump out: ```ruby manager = Fiber.new do worker = Fiber.new do puts "2. Begin Worker" manager.transfer Fiber.current.kill puts "This should never print -- killed" end puts "1. Transfer to Worker" worker.transfer puts "3. Killing Worker" worker.transfer puts "4. Finished manager" end manager.transfer puts "5. Finished script" ``` Prints: ``` 1. Transfer to Worker 2. Begin Worker 3. Killing Worker 5. Finished script ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/