チケット #3050 が更新されました。 (by Yusuke Endoh)

カテゴリ coreにセット
担当者 Koichi Sasadaにセット
Target version 1.9.2にセット
ruby -v -にセット

遠藤です。

>  現在,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>
----------------------------------------
http://redmine.ruby-lang.org/issues/show/3050

----------------------------------------
http://redmine.ruby-lang.org