2009-02-13 2 views
3

В моем приложении Rails у меня есть скрипт, который обновляет некоторые записи в базе данных. Когда я отправляю SIGTERM, чтобы убить скрипт, он иногда получает этот сигнал, в то время как ActiveRecord выполняет запрос. Это приводит к возникновению исключения ActiveRecord :: StatementInvalid.ActiveRecord :: StatementInvalid, когда процесс получает SIGTERM?

Я хотел бы уловить исключения StatementInvalid, которые возникают, когда они являются результатом SIGTERM и выходят из сценария. Как я могу сказать, что StatementInvalid происходит из-за сигнала, а не по какой-либо другой причине?

+0

Есть ли что-то еще, что вы ищете, чтобы закрыть этот вопрос? – wuputah

ответ

0

Похоже, что этот «скрипт» является внешним для приложения Rails (script/runner или аналогичным?), Поэтому, возможно, вы можете отделить «обработчик сигналов» и «рабочий»? Например, вы можете разветвить дочерний процесс/thread/fiber/... для обновления базы данных и сигнализировать родительскому лицу, чтобы указать «остановить сейчас»? Разумеется, родитель должен «сигнализировать» ребенку, чтобы он прекратил использовать какой-то подходящий механизм (не SIGTERM ;-)).

5

Если вы улавливаете сигнал TERM, я считаю, что вы избежите исключения. Вы можете сделать это в начале вашего скрипта (или, действительно, где угодно, но вам нужно сделать это только один раз).

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

Причина вы получите ошибку StatementInvalid Раби обрабатывает сигнал, поднимая исключение SIGTERM по месту текущего исполнения. ActiveRecord улавливает исключение и реконструирует его как StatementInvalid. Установив обработчик сигналов, Ruby будет выполнять ваш обработчик вместо того, чтобы создавать исключение.

Для получения дополнительной информации см. Ruby Signal documentation.

+0

Исправлено, необходимо использовать Kernel.exit! для этого работать. Доказательство на примере: http://gist.github.com/66735 – wuputah

+0

Предполагая, что этот тип выхода «нормальный», вы, вероятно, хотите «Kernel.exit! true'. По завершении процесса процесс завершится со статусом 0. – johnf

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 
Смежные вопросы