当进程收到SIGTERM时,ActiveRecord :: StatementInvalid?

时间:2009-02-13 23:09:21

标签: ruby-on-rails sigterm

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

我想捕获当它们是SIGTERM的结果并退出脚本时发生的StatementInvalid异常。如何判断由于信号而发生StatementInvalid而不是出于其他原因?

3 个答案:

答案 0 :(得分:5)

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

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

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

有关详细信息,请参阅Ruby Signal documentation

答案 1 :(得分:0)

听起来这个“脚本”在Rails应用程序外部(script/runner或类似的?),所以也许你可以解耦“信号处理程序”和“工作者”?例如,您可以分叉子进程/线程/光纤/ ...进行数据库更新,并通知父进程指示“立即停止”?当然,父母必须“发信号”孩子停止使用某种适当的机制(不是SIGTERM; - ))。

答案 2 :(得分:0)

这不是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