Project

General

Profile

Actions

Bug #3182

closed

multi-irb may run parallelly

Added by mame (Yusuke Endoh) almost 14 years ago. Updated almost 13 years ago.

Status:
Closed
Target version:
ruby -v:
ruby 1.9.2dev (2010-04-21 trunk 27432) [i686-linux]
Backport:
[ruby-dev:41031]

Description

=begin
いしつかさん
遠藤です。

#3139 で、irb が SEGV するという報告が上がっています。
こんな感じで再現するらしいです。

irb String
irb Array
kill String
jobs
jobs
jobs #=> SEGV

私の環境で再現はしないのですが、同じ手順を実行すると、kill したあとで、
キー入力が不思議な挙動になりました。

irb(main):001:0> irb String
irb#1(String):001:0> irb Array
irb#2(Array):001:0> kill String
=> #<IRB::Irb: @context=#IRB::Context:0x84096bc, @signal_status=:IN_EVAL, @scanner=#RubyLex:0x84080a0>
irb(main):002:0> => [String]
irb#2(Array):002:0> j
NameError: undefined local variable or method j' for main:Object from (irb):2 from ../ruby-trunk-local/bin/irb:12:in '
irb(main):003:0> obs
NameError: undefined local variable or method obs' for main:Object from (irb):3 from ../ruby-trunk-local/bin/irb:12:in '

調べてみたところ、multi-irb で複数の irb のスレッドが同時に走り出して
いて、複数のスレッドから Readline.readline を呼ぶため入力の奪い合いに
なっているようです。
たぶん、これが報告者の環境では SEGV になったのではないかと予想します
(再現しないのでわからないですが) 。

SEGV はおいといて、複数の irb スレッドが走りだすのは multi-irb のバグ
だと思います。
irb が終了したときに、親の irb スレッドを run するコードがありますが、
kill された時は kill した irb スレッドがすでに走っているので、親を run
させるべきでないと思います。

以下のように、kill された irb 一覧を保持しておいて、kill された irb の
終了時には親を起こさないようにしたところ、不思議な挙動はなくなりました。

diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
index 7bb1a7c..df9c789 100644
--- a/lib/irb/ext/multi-irb.rb
+++ b/lib/irb/ext/multi-irb.rb
@@ -19,6 +19,7 @@ module IRB
def initialize
# @jobs = [[thread, irb],...]
@jobs = []

  •  @killed_irbs = {}
     @current_job = nil
    
    end

@@ -64,6 +65,7 @@ module IRB
for key in keys
th, irb = search(key)
IRB.fail IrbAlreadyDead unless th.alive?

  •    @killed_irbs[irb] = true
    

    th.exit
    end
    end
    @@ -104,6 +106,7 @@ module IRB
    end
    until assoc = @jobs.pop; end unless @jobs.empty?
    @jobs.push assoc

  •  @killed_irbs.delete(key)
    

    end

    def inspect
    @@ -171,7 +174,7 @@ module IRB
    #fail
    ensure
    unless system_exit

  • @JobManager.delete(irb)
  • unless @JobManager.delete(irb)
    if parent_thread.alive?
    @JobManager.current_job = @JobManager.irb(parent_thread)
    parent_thread.run
    @@ -179,6 +182,7 @@ module IRB
    @JobManager.current_job = @JobManager.main_irb
    @JobManager.main_thread.run
    end
  •      end
    
    end
    end
    end

--
Yusuke Endoh
=end


Related issues 1 (0 open1 closed)

Is duplicate of Ruby master - Bug #3139: Possible Bug with Irb jobs from Ruby 1.9.2-devClosed04/13/2010Actions
Actions #1

Updated by keiju (Keiju Ishitsuka) almost 14 years ago

=begin
けいじゅ@いしつかです.

In [ruby-dev:41031] the message: "[ruby-dev:41031] [Bug #3182]
multi-irb may run parallelly", on Apr/21 20:54(JST) Yusuke Endoh
writes:

いしつかさん
遠藤です。

私の環境で再現はしないのですが、同じ手順を実行すると、kill したあとで、
キー入力が不思議な挙動になりました。

irb(main):001:0> irb String
irb#1(String):001:0> irb Array
irb#2(Array):001:0> kill String
=> #<IRB::Irb: @context=#IRB::Context:0x84096bc, @signal_status=:IN_EVAL, @scanner=#RubyLex:0x84080a0>
irb(main):002:0> => [String]
irb#2(Array):002:0> j
NameError: undefined local variable or method j' for main:Object from (irb):2 from ../ruby-trunk-local/bin/irb:12:in '
irb(main):003:0> obs
NameError: undefined local variable or method obs' for main:Object from (irb):3 from ../ruby-trunk-local/bin/irb:12:in '

SEGV はおいといて、複数の irb スレッドが走りだすのは multi-irb のバグ
だと思います。

確かに.

irb が終了したときに、親の irb スレッドを run するコードがありますが、
kill された時は kill した irb スレッドがすでに走っているので、親を run
させるべきでないと思います。

以下のように、kill された irb 一覧を保持しておいて、kill された irb の
終了時には親を起こさないようにしたところ、不思議な挙動はなくなりまし
た。

確かにこれでもよい気がしますが, 単純に その終了するsubirbがカレントジョ
ブの時のみカレントジョブの置き換えをするようにするで十分なようです. こ
ちらのパッチを採用したいと思います.

--- lib/irb/ext/multi-irb.rb (リビジョン 27443)
+++ lib/irb/ext/multi-irb.rb (作業コピー)
@@ -172,12 +172,14 @@
ensure
unless system_exit
@JobManager.delete(irb)

  • if parent_thread.alive?
  •  @JobManager.current_job = @JobManager.irb(parent_thread)
    
  •  parent_thread.run
    
  • else
  •  @JobManager.current_job = @JobManager.main_irb
    
  •  @JobManager.main_thread.run
    
  • if @JobManager.current_job == irb
  •  if parent_thread.alive?
    
  •    @JobManager.current_job = @JobManager.irb(parent_thread)
    
  •    parent_thread.run
    
  •  else
    
  •    @JobManager.current_job = @JobManager.main_irb
    
  •    @JobManager.main_thread.run
    
  •  end
    
    end
    end
    end

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: <<---

=end

Actions #2

Updated by keiju (Keiju Ishitsuka) almost 14 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r27444.
Yusuke, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Actions

Also available in: Atom PDF

Like0
Like0Like0