rubyのスクリプトの終了時に何か処理をしたい。
- エラーで落ちた時に、途中経過を保存しておきたい。
- 無事終了したら、メールを送る
- スレッドが死んだらどうするか
本来なら、ちゃんと例外処理や、ループ抜ける処理を書くべきなんです。
本来なら、ちゃんと例外処理や、ループ抜ける処理を書くべきなんです。
でも、無精したい時もあるし、すべての例外を受け止めるのもなんだかな。
終了処理を書く
とりあえず基本形
#!/usr/bin/env ruby
begin
loop{ sleep 10*10*10}
rescue SignalException => e
puts e.message
puts e.backtrace
end
実行して止める
takuya@air:~/Desktop$ ruby sinaltest.rb
^C
sinaltest.rb:4:in `sleep'
sinaltest.rb:4
sinaltest.rb:4:in `loop'
sinaltest.rb:4
スレッドの終了処理
子スレッドも終了時になんかかせたい。
#!/usr/bin/env ruby
class Bar < Thread
def Bar.callback
proc {
puts "bar"
}
end
def initialize
ObjectSpace.define_finalizer(self,Bar.callback)
super
end
end
begin
t =[]
t << Bar.new{ Thread.pass; loop{puts 1; sleep 1;Thread.pass} }
t << Thread.new{ Thread.pass; loop{puts 2; sleep 1;Thread.pass} }
loop{ puts 0; sleep 1}
rescue SignalException => e
puts e.message
puts e.backtrace
t.each{|a| a.kill}
end
実行
takuya@air:~/Desktop$ ruby sinaltest.rb
1
0
2
0
1
2
^C#⇐止める
sinaltest.rb:23:in `sleep’ #⇐rescueが実行される
sinaltest.rb:23
sinaltest.rb:23:in `loop'
sinaltest.rb:23
bar # thread.killにより、object.finalizerが実行される。
スレッドの終了処理:パターン2(一番シンプル?)
スレッド終了処理はもっとシンプルにできそう
#!/usr/bin/env ruby
class Thread
def Thread.callback
proc {
puts "bar"
}
end
end
begin
t =[]
t << Thread.new{ Thread.pass; loop{puts 1; sleep 1;Thread.pass} }
ObjectSpace.define_finalizer(t[0],Thread.callback)
loop{ puts 0; sleep 1}
rescue SignalException => e
puts e.message
puts e.backtrace
t.each{|a| a.kill}
end
クラスメソッドで共有されてProc使うのがなんか。。。
パターン3(特異クラスを使う)
#!/usr/bin/env ruby
class Thread
def Thread.callback
proc {
puts "bar"
}
end
end
begin
t =[]
t << Thread.new{ Thread.pass; loop{puts 1; sleep 1;Thread.pass} }
class << t[0]
ObjectSpace.define_finalizer(self,Thread.callback)
end
loop{ puts 0; sleep 1}
rescue SignalException => e
puts e.message
puts e.backtrace
t.each{|a| a.kill}
end
動かない例
#!/usr/bin/env ruby
class Thread
def Thread.callback
proc {
puts "bar"
}
end
ObjectSpace.define_finalizer(self,Thread.callback)
end
begin
t =[]
t << Thread.new{ Thread.pass; loop{puts 1; sleep 1;Thread.pass} }
loop{ puts 0; sleep 1}
rescue SignalException => e
puts e.message
puts e.backtrace
t.each{|a| a.kill}
end
selfが参照できないので、動かない。
スレッドが落ちたときに処理したいと思ったけどなかなか面倒なのでした