Bug #6117
Transfers allowed into Fibers that have resumed into other fibers
Description
Consider the following code:
require 'fiber'
def foo
order = []
main_fiber = Fiber.current
a = Fiber.new do
order << 2
x = Fiber.new do
order << 4
main_fiber.transfer
order << 6
end
order << 3
x.resume
order << 7
end
order << 1
a.transfer
order << 5
a.transfer
order << 8
end
It produces output:
[1, 2, 3, 4, 5, 7, 8]
Note: the missing 6. I'd expect either the array to be 1-8 OR for an exception to be raised after 5 when the main fiber attempts to transfer into a again.
Either it shouldn't be possible to transfer into a Fiber that is blocked resuming another Fiber, OR it should automatically resume the sub-Fiber.
Updated by mrkn (Kenta Murata) almost 9 years ago
- Assignee set to ko1 (Koichi Sasada)
Updated by ko1 (Koichi Sasada) about 8 years ago
Exception seems good.
transfer' and
resume' should not be mix.
Any volunteer?
or it will be tagged `next minor'.
Updated by ko1 (Koichi Sasada) about 8 years ago
- Target version changed from 2.0.0 to 2.6
no volunteer.
Updated by ko1 (Koichi Sasada) over 5 years ago
- Description updated (diff)
- Status changed from Assigned to Feedback
Updated by jeremyevans0 (Jeremy Evans) about 1 year ago
- Assignee changed from ko1 (Koichi Sasada) to ioquatix (Samuel Williams)
I do not think this code is actually a problem. The restriction on transferred fibers is:
You cannot resume a fiber that transferred control to another one. This will cause a double resume error. You need to transfer control back to this fiber before it can yield and resume.
That is not happening in this case. main_fiber
transfers to a
, which resumes x
, which transfers back to main_fiber
, which transfers again to a
. At no point is a fiber that has transferred control to another fiber resumed before control is transferred back to the fiber.
In the example given x
is not transferred back to after it transfers to main_fiber
, which is why 6
does not appear in the output. You can fix this by having a
transfer to x
after it is transferred back to (the second time) from main_fiber
:
require 'fiber'
def foo
order = []
main_fiber = Fiber.current
a = Fiber.new do
order << 2
x = Fiber.new do
order << 4
main_fiber.transfer
order << 6
end
order << 3
x.resume
x.transfer
order << 7
end
order << 1
a.transfer
order << 5
a.transfer
order << 8
end
Assinging to ioquatix (Samuel Williams) to determine if this is actually a bug.