Fix Fiber#transfer
Fiber#transfer previously made it impossible to resume the fiber if it was transferred to (no resuming the target of Fiber#transfer). However, the documentation specifies that you cannot resume a fiber that has transferred to another fiber (no resuming the source of Fiber#transfer), unless control is transferred back. Fix the code by setting the transferred flag on the current/source fiber, and unsetting the transferred flag on the target fiber. Fixes [Bug #9664] Fixes [Bug #12555]
This commit is contained in:
parent
f37cc1c719
commit
fa8ac91e95
Notes:
git
2019-10-22 08:55:22 +09:00
Merged: https://github.com/ruby/ruby/pull/2588 Merged-By: jeremyevans <code@jeremyevans.net>
3
cont.c
3
cont.c
@ -2226,7 +2226,8 @@ static VALUE
|
|||||||
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
|
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
|
||||||
{
|
{
|
||||||
rb_fiber_t *fiber = fiber_ptr(fiber_value);
|
rb_fiber_t *fiber = fiber_ptr(fiber_value);
|
||||||
fiber->transferred = 1;
|
fiber_current()->transferred = 1;
|
||||||
|
fiber->transferred = 0;
|
||||||
return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT);
|
return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,9 +42,18 @@ describe "Fiber#transfer" do
|
|||||||
fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end]
|
fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises a FiberError when transferring to a Fiber which resumes itself" do
|
ruby_version_is ''...'2.7' do
|
||||||
fiber = Fiber.new { fiber.resume }
|
it "raises a FiberError when transferring to a Fiber which resumes itself" do
|
||||||
-> { fiber.transfer }.should raise_error(FiberError)
|
fiber = Fiber.new { fiber.resume }
|
||||||
|
-> { fiber.transfer }.should raise_error(FiberError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is '2.7' do
|
||||||
|
it "allows transferring to a Fiber which resumes itself" do
|
||||||
|
fiber = Fiber.new { fiber.resume 1 }
|
||||||
|
fiber.transfer.should == 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "works if Fibers in different Threads each transfer to a Fiber in the same Thread" do
|
it "works if Fibers in different Threads each transfer to a Fiber in the same Thread" do
|
||||||
|
@ -222,8 +222,8 @@ class TestFiber < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_resume_self
|
def test_resume_self
|
||||||
f = Fiber.new {f.resume}
|
f = Fiber.new {f.resume 1}
|
||||||
assert_raise(FiberError, '[ruby-core:23651]') {f.transfer}
|
assert_equal(1, f.transfer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fiber_transfer_segv
|
def test_fiber_transfer_segv
|
||||||
@ -289,14 +289,12 @@ class TestFiber < Test::Unit::TestCase
|
|||||||
assert_raise(FiberError){
|
assert_raise(FiberError){
|
||||||
g=nil
|
g=nil
|
||||||
f=Fiber.new{
|
f=Fiber.new{
|
||||||
g.resume
|
g.transfer
|
||||||
g.resume
|
|
||||||
}
|
}
|
||||||
g=Fiber.new{
|
g=Fiber.new{
|
||||||
f.resume
|
f.resume
|
||||||
f.resume
|
|
||||||
}
|
}
|
||||||
f.transfer
|
f.resume
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user