From: Yusuke Endoh Date: 2010-05-03T22:57:24+09:00 Subject: [ruby-dev:41139] [Bug #3050] Fiber transfer limitation チケット #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 ---------------------------------------- http://redmine.ruby-lang.org/issues/show/3050 ---------------------------------------- http://redmine.ruby-lang.org