Forum: Ruby-dev [ruby-trunk - Bug #6701][Open] once literal doesn't care escape

Posted by ko1 (Koichi Sasada) (Guest)
on 2012-07-05 12:03
(Received via mailing list)
Issue #6701 has been reported by ko1 (Koichi Sasada).

----------------------------------------
Bug #6701: once literal doesn't care escape
https://bugs.ruby-lang.org/issues/6701

Author: ko1 (Koichi Sasada)
Status: Open
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-07-05 trunk 36311) [i386-mswin32_100]


=begin

= 概要

/#{expr}/o は,expr はたかだか一回しか実行されない,後から評価したときは expr 
の評価値(を用いた正規表現)が返されるという意味になります.しかし,expr 中で例外などで大域脱出が発生し,再度評価しようとすると,まだ 
expr は実行中であると認識されるため,ブロックします.

= 現象

次のようなコードが止まりません.

  2.times{
    catch(:escape){
      p:before
      r = /#{throw :escape}/o
      # まだ,1度目の処理が終わってないとみなされているため,
      # 2回目に実行しようとすると,その1度目の終了を待つ
      # (もちろん,1度目は throw によって cancel されている→デッドロック)
      p:after
    }
  }

スレッドを絡めるとこんな感じです.

  (1..2).map{
    Thread.new{
      begin
        r = /#{raise}/o
        # あるスレッドが実行しようとするが,例外でキャンセルされる
        # 別のスレッドは,キャンセルされた実行の終了を待つ
        # (もちろん,終わるわけがないのでデッドロック)
      rescue
        p :raised
      ensure
        p :exit
      end
    }
  }.each{|t| t.join}

= 修正案

expr が例外でキャンセルされたら,ちゃんと「未実行状態」に戻して,待ってるスレッドがいればそのスレッドが expr 
をやり直すべきではないかと思います.具体的には,ちゃんと ensure 的な処理を入れる様に改造します.

特に何も意見がなければ,2.0 はこの方針で直します.

1.9 は,もうこのまま,でしょうか.これまで文句が来たことが無いので,誰も /#{expr}/o なんて使ってないってことですかね.

別の選択肢として,例外で抜けたら expr の評価値を nil にする,という案もありますが,なぜ nil 
なのか,とかあまり説得力のある理由が思いつきません.

= 余談

ところで,これを考えていて,次の様な例が思い当たりました.

  def foo
    r = /#{foo}/o
  end

  foo

これ,どうするべきなんだろう.こんなこと書くな,でしょうか.それとも,deadlock というか,recursive な once 
なのでエラー,とするのがいいでしょうか(エラーがいい気がするな).

ちなみに,1.8 だと問答無用で実行しちゃうようで:

  t.rb:3:in `foo': stack level too deep (SystemStackError)


=end
Posted by mame (Yusuke Endoh) (Guest)
on 2012-07-05 14:24
(Received via mailing list)
Issue #6701 has been updated by mame (Yusuke Endoh).

Status changed from Open to Assigned

遠藤です。

2012年7月5日 19:02 ko1 (Koichi Sasada) <redmine@ruby-lang.org>:
> しかし,expr 中で例外などで大域脱出が発生し,再度評価しようとすると,まだ expr は実行中であると認識されるため,ブロックします.

この問題は認識してましたが、以下の通りサボってました。

http://bugs.ruby-lang.org/issues/show/2398


> 特に何も意見がなければ,2.0 はこの方針で直します.

賛成です。直してください。

--
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Bug #6701: once literal doesn't care escape
https://bugs.ruby-lang.org/issues/6701#change-27828

Author: ko1 (Koichi Sasada)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-07-05 trunk 36311) [i386-mswin32_100]


=begin

= 概要

/#{expr}/o は,expr はたかだか一回しか実行されない,後から評価したときは expr 
の評価値(を用いた正規表現)が返されるという意味になります.しかし,expr 中で例外などで大域脱出が発生し,再度評価しようとすると,まだ 
expr は実行中であると認識されるため,ブロックします.

= 現象

次のようなコードが止まりません.

  2.times{
    catch(:escape){
      p:before
      r = /#{throw :escape}/o
      # まだ,1度目の処理が終わってないとみなされているため,
      # 2回目に実行しようとすると,その1度目の終了を待つ
      # (もちろん,1度目は throw によって cancel されている→デッドロック)
      p:after
    }
  }

スレッドを絡めるとこんな感じです.

  (1..2).map{
    Thread.new{
      begin
        r = /#{raise}/o
        # あるスレッドが実行しようとするが,例外でキャンセルされる
        # 別のスレッドは,キャンセルされた実行の終了を待つ
        # (もちろん,終わるわけがないのでデッドロック)
      rescue
        p :raised
      ensure
        p :exit
      end
    }
  }.each{|t| t.join}

= 修正案

expr が例外でキャンセルされたら,ちゃんと「未実行状態」に戻して,待ってるスレッドがいればそのスレッドが expr 
をやり直すべきではないかと思います.具体的には,ちゃんと ensure 的な処理を入れる様に改造します.

特に何も意見がなければ,2.0 はこの方針で直します.

1.9 は,もうこのまま,でしょうか.これまで文句が来たことが無いので,誰も /#{expr}/o なんて使ってないってことですかね.

別の選択肢として,例外で抜けたら expr の評価値を nil にする,という案もありますが,なぜ nil 
なのか,とかあまり説得力のある理由が思いつきません.

= 余談

ところで,これを考えていて,次の様な例が思い当たりました.

  def foo
    r = /#{foo}/o
  end

  foo

これ,どうするべきなんだろう.こんなこと書くな,でしょうか.それとも,deadlock というか,recursive な once 
なのでエラー,とするのがいいでしょうか(エラーがいい気がするな).

ちなみに,1.8 だと問答無用で実行しちゃうようで:

  t.rb:3:in `foo': stack level too deep (SystemStackError)


=end
Posted by ko1 (Koichi Sasada) (Guest)
on 2012-11-26 01:49
(Received via mailing list)
Issue #6701 has been updated by ko1 (Koichi Sasada).


これ,preview 2 の後でも許されますか?
許されないなら next minor 行き.
----------------------------------------
Bug #6701: once literal doesn't care escape
https://bugs.ruby-lang.org/issues/6701#change-33921

Author: ko1 (Koichi Sasada)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-07-05 trunk 36311) [i386-mswin32_100]


=begin

= 概要

/#{expr}/o は,expr はたかだか一回しか実行されない,後から評価したときは expr 
の評価値(を用いた正規表現)が返されるという意味になります.しかし,expr 中で例外などで大域脱出が発生し,再度評価しようとすると,まだ 
expr は実行中であると認識されるため,ブロックします.

= 現象

次のようなコードが止まりません.

  2.times{
    catch(:escape){
      p:before
      r = /#{throw :escape}/o
      # まだ,1度目の処理が終わってないとみなされているため,
      # 2回目に実行しようとすると,その1度目の終了を待つ
      # (もちろん,1度目は throw によって cancel されている→デッドロック)
      p:after
    }
  }

スレッドを絡めるとこんな感じです.

  (1..2).map{
    Thread.new{
      begin
        r = /#{raise}/o
        # あるスレッドが実行しようとするが,例外でキャンセルされる
        # 別のスレッドは,キャンセルされた実行の終了を待つ
        # (もちろん,終わるわけがないのでデッドロック)
      rescue
        p :raised
      ensure
        p :exit
      end
    }
  }.each{|t| t.join}

= 修正案

expr が例外でキャンセルされたら,ちゃんと「未実行状態」に戻して,待ってるスレッドがいればそのスレッドが expr 
をやり直すべきではないかと思います.具体的には,ちゃんと ensure 的な処理を入れる様に改造します.

特に何も意見がなければ,2.0 はこの方針で直します.

1.9 は,もうこのまま,でしょうか.これまで文句が来たことが無いので,誰も /#{expr}/o なんて使ってないってことですかね.

別の選択肢として,例外で抜けたら expr の評価値を nil にする,という案もありますが,なぜ nil 
なのか,とかあまり説得力のある理由が思いつきません.

= 余談

ところで,これを考えていて,次の様な例が思い当たりました.

  def foo
    r = /#{foo}/o
  end

  foo

これ,どうするべきなんだろう.こんなこと書くな,でしょうか.それとも,deadlock というか,recursive な once 
なのでエラー,とするのがいいでしょうか(エラーがいい気がするな).

ちなみに,1.8 だと問答無用で実行しちゃうようで:

  t.rb:3:in `foo': stack level too deep (SystemStackError)


=end
Posted by ko1 (Koichi Sasada) (Guest)
on 2012-12-19 23:46
(Received via mailing list)
Issue #6701 has been updated by ko1 (Koichi Sasada).

Target version changed from 2.0.0 to next minor

timeup.

----------------------------------------
Bug #6701: once literal doesn't care escape
https://bugs.ruby-lang.org/issues/6701#change-34873

Author: ko1 (Koichi Sasada)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: next minor
ruby -v: ruby 2.0.0dev (2012-07-05 trunk 36311) [i386-mswin32_100]


=begin

= 概要

/#{expr}/o は,expr はたかだか一回しか実行されない,後から評価したときは expr 
の評価値(を用いた正規表現)が返されるという意味になります.しかし,expr 中で例外などで大域脱出が発生し,再度評価しようとすると,まだ 
expr は実行中であると認識されるため,ブロックします.

= 現象

次のようなコードが止まりません.

  2.times{
    catch(:escape){
      p:before
      r = /#{throw :escape}/o
      # まだ,1度目の処理が終わってないとみなされているため,
      # 2回目に実行しようとすると,その1度目の終了を待つ
      # (もちろん,1度目は throw によって cancel されている→デッドロック)
      p:after
    }
  }

スレッドを絡めるとこんな感じです.

  (1..2).map{
    Thread.new{
      begin
        r = /#{raise}/o
        # あるスレッドが実行しようとするが,例外でキャンセルされる
        # 別のスレッドは,キャンセルされた実行の終了を待つ
        # (もちろん,終わるわけがないのでデッドロック)
      rescue
        p :raised
      ensure
        p :exit
      end
    }
  }.each{|t| t.join}

= 修正案

expr が例外でキャンセルされたら,ちゃんと「未実行状態」に戻して,待ってるスレッドがいればそのスレッドが expr 
をやり直すべきではないかと思います.具体的には,ちゃんと ensure 的な処理を入れる様に改造します.

特に何も意見がなければ,2.0 はこの方針で直します.

1.9 は,もうこのまま,でしょうか.これまで文句が来たことが無いので,誰も /#{expr}/o なんて使ってないってことですかね.

別の選択肢として,例外で抜けたら expr の評価値を nil にする,という案もありますが,なぜ nil 
なのか,とかあまり説得力のある理由が思いつきません.

= 余談

ところで,これを考えていて,次の様な例が思い当たりました.

  def foo
    r = /#{foo}/o
  end

  foo

これ,どうするべきなんだろう.こんなこと書くな,でしょうか.それとも,deadlock というか,recursive な once 
なのでエラー,とするのがいいでしょうか(エラーがいい気がするな).

ちなみに,1.8 だと問答無用で実行しちゃうようで:

  t.rb:3:in `foo': stack level too deep (SystemStackError)


=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.