From: "ioquatix (Samuel Williams) via ruby-core" <ruby-core@...>
Date: 2023-12-27T21:39:41+00:00
Subject: [ruby-core:115940] [Ruby master Bug#20081] Transfered Fiber doesn't return to Fiber that started it

Issue #20081 has been updated by ioquatix (Samuel Williams).


My initial feeling is that this is not a bug.

Transferring to a fiber is a uni-directional operation and no information is expected to be kept about the caller. If that is what you desire, use resume.

There is nothing that prevents you from using resume and then transfer.

If you do desire to transfer back to a specific fiber, you can code to that, e.g.

```ruby
manager = Fiber.new do
  parent = Fiber.current
  worker = Fiber.new do
    puts "2. Begin Worker"
    parent.transfer
    puts "4. End Worker"
  ensure
    # Exit:
    parent.transfer
  end

  puts "1. Transfer 1"
  worker.transfer
  puts "3. Transfer 2"
  worker.transfer
  puts "5. Finished manager"
end

manager.transfer
puts "6. Finished script"
```

I don't know if there is a better semantic worth trying to tease out of this, but the semantics of `transfer` are fairly straight forward and I'm not sure we should change it as the chance of breaking something is probably fairly high.


----------------------------------------
Bug #20081: Transfered Fiber doesn't return to Fiber that started it
https://bugs.ruby-lang.org/issues/20081#change-105893

* Author: rmosolgo (Robert Mosolgo)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-darwin22]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Hi! I'm trying to figure out how to make sure that Fibers started with `.transfer` end up _terminated_, not just suspended. (If they're suspended, Rails thinks they're still alive, and they continue to hold onto database connections, see: https://github.com/rmosolgo/graphql-ruby/issues/4739#issuecomment-1866930914.)

So, I'm looking for way to make sure that any Fiber I start with `.transfer` will be properly terminated. But what I noticed is that when a transfer-based Fiber terminates, it gives control back to the top-most Fiber, not the Fiber which transfered to it. Is this intended? Here's a script to replicate the issue: 


```ruby
manager = Fiber.new do
  parent = Fiber.current
  worker = Fiber.new do
    puts "2. Begin Worker"
    parent.transfer
    puts "4. End Worker"
  end

  puts "1. Transfer 1"
  worker.transfer
  puts "3. Transfer 2"
  worker.transfer
  puts "5. Finished manager"
end

manager.transfer
puts "6. Finished script"
```

I expect the steps to print in order: 

```
1. Transfer 1
2. Begin Worker
3. Transfer 2
4. End Worker
5. Finished manager
6. Finished script
```

But instead, `5. ...` is skipped: 

```
1. Transfer 1
2. Begin Worker
3. Transfer 2
4. End Worker
6. Finished script
```

I think that's because my `worker` fiber terminates and passes control back to the top-level Fiber. 

Should it have passed control back to the `manager`? Or is there another way to make sure `worker` is terminated, and `manager` gets control?



-- 
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/