けいじゅ@日本ラショナルソフトウェアです.

スレッドに関して, どうも良く分からないので教えて下さい.

irbの話しなのですが, 内部で新しいirbを立ちあげる時にthreadを起動してい
ます. 子を立ちあげると, 親irbはThread.stopします. そして, 子irbを抜け
ると, 親irbをrunするようにしています. 

以下のようなコードになっています.

  # irb起動
  def IRB.irb(file = nil, *main)
    workspace = IRB.workspace_binding(*main)
    if main.empty?
      main = eval("self", workspace)
    else
      main = main[0]
    end
    irb = Irb.new(main, workspace, file)
    th = Thread.current
    Thread.start do
      #Thread.pass
      @Thread2Irb[Thread.current] = irb
      begin
	catch(:IRB_EXIT) do
	  irb.run                              # <-- 子irbの立ちあげ
	end
      ensure
	@Thread2Irb[Thread.current] = nil
	if th.alive?                           # 親はいきているか?
	  p th.stop?                           
	  p Thread.critical
	  th.run
	else
	  @Thread2Irb.keys[0].run
	end
      end
    end
    print "zzzzzzzzz"
    Thread.stop
  end

これを実行すると, 以下のようになります.

dim% ruby irb.rb
irb:001:0> irb
irb#1:001:0> exit
false
false
zzzzzzzzzirb.rb:252:deadlock 0x400fb7e4: 1:0 (main)

で, デッドロックになってしまいます. 詳しく分析すると, 子スレッドが立ち
上がった後, 親スレッドに処理が回らなくて, Thread.stopに行かないためな
のが分かります.

試しに, Thread.passを入れるとちゃんと動作します.

また,

irb#1:001:0> Thread.critical
false
irb#1:003:0> IRB.Thread2Irb.keys
[#<Thread:0x400fb7e4>, #<Thread:0x401286b8>]
irb#1:004:0> Thread.current
#<Thread:0x401286b8>
irb#1:005:0> IRB.Thread2Irb.keys[0].alive?
true
irb#1:006:0> IRB.Thread2Irb.keys[0].stop?
false

この結果のように, Thread.critical==falseです. 

こういうことって起こり得るんですかね?

__
..............................石塚 圭樹@日本ラショナルソフトウェア...
----------------------------------->> e-mail: keiju / rational.com <<---