Bug #3050
closedFiber transfer limitation
Description
=begin
ささだです.
1.9.2 に入れて欲しい Fiber に関する仕様変更について,一つ忘れていました.
現在,Fiber#transfer と Fiber.yield/Fiber#resume は一緒に使うな,使っ
て変なことが起きても知らないよ,という立場を取っています.というのも,一
緒に使うと簡単に SEGV させることが出来るからです.
例:
require 'fiber'
f2 = nil
f1 = Fiber.new{
p :f1_start
f2.resume
p :f1_end
}
f2 = Fiber.new{
p :f2_start
f1.resume
p :f2_end
}
f1.transfer
#=>
ruby 1.9.2dev (2010-03-16 trunk 26952) [i386-mswin32_90]
:f1_start
:f2_start
:f1_end
:f2_end
[BUG] Segmentation fault
例えば前者が出来るクラスを Coroutine,後者が出来るクラスを
SemiCoroutine として提供して混ぜないようにするという手段もあるのですが,
大クラス主義の Ruby とはなじみません.
そこで,Fiber#resume をした,つまり Fiber.yield する先がある Fiber に
関しては transfer を禁止しようと思います.また,一度でも Fiber#transfer
された先の Fiber を resume 出来ないようにしようと思います.
ちょっと,この制限で十分なのか,検討が足りてないんですが.¶
例だと,f1.resume の時点で例外が飛ぶことになります.
混ぜるな危険,としていたと思うので,この変更で困る人はあんまりいないん
じゃないかなぁと思います.というか,SEGV するバグなので回避しなきゃ
なぁ,という感じです.
バタバタとすみませんが,ご検討下さい.
--
// SASADA Koichi at atdot dot net
=end
Updated by matz (Yukihiro Matsumoto) over 14 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:40833] [Bug: trunk] Fiber transfer limitation"
on Tue, 30 Mar 2010 04:19:56 +0900, SASADA Koichi ko1@atdot.net writes:
| 1.9.2 に入れて欲しい Fiber に関する仕様変更について,一つ忘れていました.
|
| 現在,Fiber#transfer と Fiber.yield/Fiber#resume は一緒に使うな,使っ
|て変なことが起きても知らないよ,という立場を取っています.というのも,一
|緒に使うと簡単に SEGV させることが出来るからです.
| そこで,Fiber#resume をした,つまり Fiber.yield する先がある Fiber に
|関しては transfer を禁止しようと思います.また,一度でも Fiber#transfer
|された先の Fiber を resume 出来ないようにしようと思います.
暗黙の禁止はドキュメントに書いても誰も読まないので(いいす
ぎ?)、明示的に禁止するのは良いことではないかと思います。
=end
Updated by mame (Yusuke Endoh) over 14 years ago
- Category set to core
- Assignee set to ko1 (Koichi Sasada)
- Target version set to 1.9.2
- ruby -v set to -
=begin
遠藤です。
現在,Fiber#transfer と Fiber.yield/Fiber#resume は一緒に使うな,使っ
て変なことが起きても知らないよ,という立場を取っています.というのも,一
緒に使うと簡単に SEGV させることが出来るからです.
混ぜると理解困難な挙動になるのは確かなんですが、SEGV するとは
知りませんでした。
この例に関しては、最後のパッチで SEGV はしなくなると思います。
例えば前者が出来るクラスを Coroutine,後者が出来るクラスを
SemiCoroutine として提供して混ぜないようにするという手段もあるのですが,
大クラス主義の Ruby とはなじみません.
大クラス主義は「概念的に似ているものに複数のクラスを作らない」
だと思います。
Coroutine と SemiCoroutine は実装はほとんど共通しているものの、
概念的にはかなり異なっていると感じます。goto と function call
くらいには違いますよね。
なので、別の名前にしてもよかったんじゃないかなあ。今更ですが。
[ruby-dev:31596] 以来、transfer は用途がわからないわりに混乱を
招くと言う「百害あって一利なし」だと思うので、なければよかった
のにと思っています。
diff --git a/cont.c b/cont.c
index 185d812..b4b486d 100644
--- a/cont.c
+++ b/cont.c
@@ -945,9 +945,15 @@ fiber_switch(VALUE fibval, int argc, VALUE *argv, int is_resume)
}
else if (fib->status == TERMINATED) {
value = rb_exc_new2(rb_eFiberError, "dead fiber called");
- if (th->fiber != fibval) rb_exc_raise(value);
- fibval = fib->prev;
- if (NIL_P(fibval)) fibval = th->root_fiber;
- if (th->fiber != fibval) {
-
GetFiberPtr(th->fiber, fib);
-
if (fib->status != TERMINATED) rb_exc_raise(value);
-
fibval = th->root_fiber;
- }
- else {
-
fibval = fib->prev;
-
if (NIL_P(fibval)) fibval = th->root_fiber;
- }
GetFiberPtr(fibval, fib);
cont = &fib->cont;
cont->argc = -1;
--
Yusuke Endoh mame@tsg.ne.jp
=end
Updated by ko1 (Koichi Sasada) over 14 years ago
=begin
ささだです.
(2010/05/03 22:57), Yusuke Endoh wrote::
現在,Fiber#transfer と Fiber.yield/Fiber#resume は一緒に使うな,使っ
て変なことが起きても知らないよ,という立場を取っています.というのも,一
緒に使うと簡単に SEGV させることが出来るからです.混ぜると理解困難な挙動になるのは確かなんですが、SEGV するとは
知りませんでした。
この例に関しては、最後のパッチで SEGV はしなくなると思います。
新しい仕様を考えるのはしんどそうだし,SEGV しなくなればとりあえず良い
と思いますので,遠藤さんを信じます.
例えば前者が出来るクラスを Coroutine,後者が出来るクラスを
SemiCoroutine として提供して混ぜないようにするという手段もあるのですが,
大クラス主義の Ruby とはなじみません.大クラス主義は「概念的に似ているものに複数のクラスを作らない」
だと思います。
Coroutine と SemiCoroutine は実装はほとんど共通しているものの、
概念的にはかなり異なっていると感じます。goto と function call
くらいには違いますよね。
なので、別の名前にしてもよかったんじゃないかなあ。今更ですが。[ruby-dev:31596] 以来、transfer は用途がわからないわりに混乱を
招くと言う「百害あって一利なし」だと思うので、なければよかった
のにと思っています。
continuation と合わせて,gem とかに追い出しちゃえばよかったかなぁ.
ちなみに,Control flow を制御する,という意味で,私の中ではやっぱり同
じものってカテゴリーに.
--
// SASADA Koichi at atdot dot net
=end
Updated by ko1 (Koichi Sasada) over 14 years ago
=begin
ささだです.
(2010/05/03 22:57), Yusuke Endoh wrote::
現在,Fiber#transfer と Fiber.yield/Fiber#resume は一緒に使うな,使っ
て変なことが起きても知らないよ,という立場を取っています.というのも,一
緒に使うと簡単に SEGV させることが出来るからです.混ぜると理解困難な挙動になるのは確かなんですが、SEGV するとは
知りませんでした。
この例に関しては、最後のパッチで SEGV はしなくなると思います。
新しい仕様を考えるのはしんどそうだし,SEGV しなくなればとりあえず良い
と思いますので,遠藤さんを信じます.
例えば前者が出来るクラスを Coroutine,後者が出来るクラスを
SemiCoroutine として提供して混ぜないようにするという手段もあるのですが,
大クラス主義の Ruby とはなじみません.大クラス主義は「概念的に似ているものに複数のクラスを作らない」
だと思います。
Coroutine と SemiCoroutine は実装はほとんど共通しているものの、
概念的にはかなり異なっていると感じます。goto と function call
くらいには違いますよね。
なので、別の名前にしてもよかったんじゃないかなあ。今更ですが。[ruby-dev:31596] 以来、transfer は用途がわからないわりに混乱を
招くと言う「百害あって一利なし」だと思うので、なければよかった
のにと思っています。
continuation と合わせて,gem とかに追い出しちゃえばよかったかなぁ.
ちなみに,Control flow を制御する,という意味で,私の中ではやっぱり同
じものってカテゴリーに.
--
// SASADA Koichi at atdot dot net
=end
Updated by mame (Yusuke Endoh) over 14 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
=begin
This issue was solved with changeset r27713.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
=end