2009-04-15 59 views
1

什麼是active_record對windows下的信號進程做了什麼(我沒有在mac上看到與這個版本相同的版本),導致它表現得如此奇怪?例如:Ruby,windows,active_record和Control-C

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

當我運行上面的代碼(紅寶石1.8.6,1.3.1寶石,ActiveRecord的2.2.2)我可以打^ C多次,我先睡一覺期間喜歡,但在activerecord要求之後的第一個中斷會導致腳本終止。在上述情況下,陷阱仍然執行,它只是不能讓程序繼續。通常。

刪除第二次陷阱調用對行爲沒有任何影響。

真正的煩惱是,在某些情況下,陷阱根本無法執行。考慮到這樣做的關鍵是讓我的代碼自行清理(刪除其在數據庫中的足跡以便下一個人看到一個理智的狀態),這是一個真正的問題。例如:

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

看到投入後按^ C將根本不執行陷阱。

我只看到這個問題後,需要active_record。有沒有解決方法?我很想知道這是否是一個錯誤,或者是否有某種解釋。正如我所說的,我沒有任何問題在mac上重複的^ Cs導致多次執行陷阱過程。

感謝...

+0

嘿,它是Windows上的Ruby。只是很高興,它沒有設置你的機器着火(我認爲他們修復了這個bug在1.4)。 – Pesto 2009-04-15 23:55:02

+0

只是好奇,但爲什麼有必要捕捉任何SIGINT,而不是搶救你的代碼的一部分ruby的中斷異常?也許縮小你的解決方案以適應長時間運行的過程就足夠了,而不是在代碼中的任何地方捕捉任何* SIGINT *。 – 2010-01-20 19:42:49

回答

1

考慮到這樣做的整點是讓我的代碼清理後本身(刪除數據庫中的其足跡......

有你考慮只是使用數據庫事務?似乎這將是一個更容易的方法來解決問題。

0

當我試圖重複此問題時看到了不同的模式:

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

在Ubuntu(紅寶石1.8.6)這產生

start 
interrupted 
interrupted 
(etc) 
interrupted 
end 

因此, 「中斷」 的每個被按壓鍵Crtl-C時間打印,直到5秒之後。在Windows(也紅寶石1.8.6),這產生了:

start 
interrupted 
end 

即,它輸出 「打斷」 一次,然後退出。

所以看起來,在處理SIGINT時,Ruby會退出睡眠例程並繼續執行下一個語句。我的猜測(手搖)是由於Ruby使用綠色線程而不是Windows上的本地線程。任何專家請在這裏點贊。

您可以通過在處理程序重新啓動sleep模仿了Unix-Y的行​​爲:

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) 
相關問題