スレッド一覧を表示する。
プログラム終了時に残存スレッドがあるっぽいので調査。とりあえず、スレッドの一覧は、「Thread#list」で取得できる。
# スレッド作成 (0..3).map {|i| Thread.start { loop { sleep 0.1 } } } # スレッドの起動を待つ sleep 0.5 # スレッド一覧を表示 puts Thread.list
実行結果です。
#<Thread:0x1042f8c8> #<Thread:0x1042f97c> #<Thread:0x1042fa30> #<Thread:0x1042fae4> #<Thread:0x1043de50>
うーん、これだとスレッドがどこの誰だかわからんなー。ということで、スレッドで作成元のスタックトレースを覚えるようにしてみた。といっても、スレッド起動時に「caller」の値を取得してスレッドに設定しておくだけだけど。
clazz = class << Thread; self; end clazz.__send__(:alias_method, :start_org, :start ) def Thread.start(*args, &b) t = Thread.start_org( *args, &b) t[:stack] = caller # callerをスレッドに積む return t end # スレッド作成 (0..3).map {|i| Thread.start { loop { sleep 0.1 } } } # スレッドの起動を待つ sleep 0.5 # スレッド一覧を表示 Thread.list.each {|t| puts "---#{t}" puts t[:stack] }
ちゃんとするなら、「Thread#new」とか「Thread#fork」も上書きしないとだめ。実行結果は以下。
---#<Thread:0x1042fc10> xxx/test.rb:27 xxx/test.rb:37:in `map' xxx/test.rb:26:in `each' xxx/test.rb:26:in `map' xxx/test.rb:26 ---#<Thread:0x1042fd78> xxx/test.rb:27 xxx/test.rb:37:in `map' xxx/test.rb:26:in `each' xxx/test.rb:26:in `map' xxx/test.rb:26 ---#<Thread:0x1042fee0> xxx/test.rb:27 xxx/test.rb:37:in `map' xxx/test.rb:26:in `each' xxx/test.rb:26:in `map' xxx/test.rb:26 ---#<Thread:0x10430048> xxx/test.rb:27 xxx/test.rb:37:in `map' xxx/test.rb:26:in `each' xxx/test.rb:26:in `map' xxx/test.rb:26 ---#<Thread:0x1043de50> nil
これで作成元がわかると。スレッドダンプツールとか探せばありそうだけど、まぁとりあえずこれで調査はできるかな。