进程收到SIGTERM时ActiveRecord :: StatementInvalid?

问题描述:

在我的Rails应用程序中,我有一个更新数据库中某些记录的脚本。当我发送一个SIGTERM来终止脚本时,它偶尔会在ActiveRecord执行查询时收到该信号。这导致引发ActiveRecord :: StatementInvalid异常。进程收到SIGTERM时ActiveRecord :: StatementInvalid?

我想赶上时,他们他们是一个SIGTERM的结果,并退出脚本发生StatementInvalid例外。我如何知道由于信号而导致StatementInvalid出现而不是出于其他原因?

+0

是否还有其他的东西你想要关闭这个问题? – wuputah 2010-08-25 19:48:52

这听起来像这个“剧本”是外部Rails应用程序(script/runner或相似?),所以也许你可以断开的“信号处理器”和“工人”?例如,你可以派生一个子进程/线程/光纤/ ...来做数据库更新,并发信号通知父母指示“立即停止”?当然,家长必须“发信号”让孩子停止使用一些适当的机制(不是SIGTERM ;-))。

如果你陷入TERM信号,我相信你会避免这个例外。您可以在脚本的开头执行此操作(或者在任何地方执行此操作,但只需执行一次操作)。

Signal.trap("TERM") do 
    Kernel.exit! 
end 

你得到StatementInvalid错误的原因是Ruby通过在当前执行的地方引发一个SIGTERM异常来处理信号。 ActiveRecord捕获异常并将其重新抛出为StatementInvalid。通过设置Signal处理程序,Ruby将执行您的处理程序,而不是引发异常。

更多信息,请参见Ruby Signal documentation

+0

修正了,一定要用Kernel.exit!为此工作。通过示例验证:http://gist.github.com/66735 – wuputah 2009-02-19 05:03:45

这不是一个确切的答案,OP,但是,你可以控制的出口点 - 该计划将只达到你所定义的退出点之后退出。

time_to_die=false 

# Prevent abrupt stopping of the daemon. 
Signal.trap("TERM") { time_to_die=true; "SIG_IGN" } 

loop { 
    . 
    . 
    exit_gracefully if time_to_die 
    . 
    . 
} 

def exit_gracefully 
    #Cleaning up.. 
    $log.log "#{Time.now} TERM signal received. Exiting.." 
    $db.close 
    exit 
end