Ruby, windows, active_record и Control-C - PullRequest
1 голос
/ 16 апреля 2009

Что делает active_record с сигнальными процессами под Windows (я не вижу этого с теми же версиями на Mac), что заставляет его вести себя так странно? Например:

require 'rubygems'
trap("INT"){puts "interrupted"}
puts __LINE__
sleep 5
require 'active_record'
trap("INT"){puts "interrupted again"}
puts __LINE__
sleep 5

Когда я запускаю приведенный выше код (ruby 1.8.6, gem 1.3.1, activerecord 2.2.2,), я могу нажимать ^ C столько раз, сколько мне нравится во время первого сна, но первое прерывание после требования activerecord вызывает завершение работы скрипта. В вышеприведенном случае ловушка все еще выполняется, она только не позволяет программе продолжаться. Обычно.

Удаление второго вызова trap не влияет на поведение.

Настоящее раздражение в том, что в некоторых условиях ловушка вообще не срабатывает. Учитывая, что весь смысл в этом состоит в том, чтобы заставить мой код очищаться после себя (удалить его след в базе данных, чтобы следующий парень увидел нормальное состояние), это реальная проблема. Например:

require 'rubygems'
require 'active_record'
trap("INT"){puts "interrupted"}
puts __LINE__
gets

Нажатие ^ C после просмотра путов вообще не будет запускать ловушку.

Я вижу эту проблему только после запроса active_record. Есть ли обходной путь? Мне было бы интересно узнать, если это ошибка или есть какое-то объяснение. Как я уже сказал, у меня нет проблем с этим на Mac - повторяющиеся ^ Cs приводят к многократному выполнению процедуры trap.

спасибо ...

Ответы [ 2 ]

1 голос
/ 16 апреля 2009

Учитывая, что весь смысл в этом состоит в том, чтобы заставить мой код убирать за собой (удалить его след в базе данных ...

Рассматривали ли вы просто использование транзакции базы данных? Похоже, это был бы гораздо более простой способ решения проблемы.

0 голосов
/ 20 января 2010

При попытке дублировать эту проблему я увидел другую схему:

puts "start"
trap("INT") { puts "interrupted" }
sleep 5
puts "end"

В Ubuntu (Ruby 1.8.6) это выдает

start
interrupted
interrupted
(etc)
interrupted
end

Таким образом, «прерванные» отпечатки каждый раз, когда нажимается Crtl-C, до тех пор, пока не истечут 5 секунд. Под Windows (также Ruby 1.8.6) это выдает:

start
interrupted
end

т.е. он печатает «прервано» один раз и затем выходит.

Похоже, что при обработке SIGINT Ruby выходит из режима сна и переходит к следующему оператору. Мое предположение (махание рукой) заключается в том, что это связано с тем, что Ruby использует зеленые потоки вместо собственных потоков в Windows. Любые эксперты, пожалуйста, перезвоните здесь.

Вы можете эмулировать поведение Unix-y, перезапустив sleep в обработчике:

puts "start"
trap("INT") do 
  puts "interrupted"
  sleep 5
end
sleep 5
puts "end"

К сожалению, это сбрасывает таймер каждый раз, когда SIGINT перехватывается, поэтому он требует некоторого взлома:

$interval = 5
def go_to_sleep(secs)
  $started = Time.now
  sleep secs
end
trap("INT") do 
  puts "interrupted"
  time_to_sleep = [0,$interval - (Time.now - $started)].max
  if time_to_sleep > 0
    sleep time_to_sleep
  end
end
puts "one"
go_to_sleep($interval)
puts "two"
go_to_sleep($interval)
puts "three"
go_to_sleep($interval)
...