Project

General

Profile

Bug #3050

Fiber transfer limitation

Added by ko1 (Koichi Sasada) almost 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
-
Backport:
[ruby-dev:40833]

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

History

#1

Updated by matz (Yukihiro Matsumoto) almost 10 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

#2

Updated by mame (Yusuke Endoh) over 9 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

#3

Updated by ko1 (Koichi Sasada) over 9 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

#4

Updated by ko1 (Koichi Sasada) over 9 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

#5

Updated by mame (Yusuke Endoh) over 9 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

Also available in: Atom PDF