這是最簡單的代碼來解釋:在popen中超時工作,但在超時內popen不?
require 'timeout'
puts "this block will properly kill the sleep after a second"
IO.popen("sleep 60") do |io|
begin
Timeout.timeout(1) do
while (line=io.gets) do
output += line
end
end
rescue Timeout::Error => ex
Process.kill 9, io.pid
puts "timed out: this block worked correctly"
end
end
puts "but this one blocks for >1 minute"
begin
pid = 0
Timeout.timeout(1) do
IO.popen("sleep 60") do |io|
pid = io.pid
while (line=io.gets) do
output += line
end
end
end
rescue Timeout::Error => ex
puts "timed out: the exception gets thrown, but much too late"
end
我的兩個塊的心智模式是相同的:
所以,我缺少什麼?
編輯:drmaciver在twitter上建議,在第一種情況下,由於某種原因,管道套接字進入非阻塞模式,但在第二種情況下不會。我想不出爲什麼會發生這種情況,我也不知道如何獲得描述符的標誌,但至少是一個合理的答案?在這個可能性上工作。
你跑哪個紅寶石? –
至少在1.8.7和1.9.3上發生此行爲。 jruby塊在這兩個塊上都是60,這是我先前猜測的行爲。 – llimllib
請注意,您爲我的兩個塊之間的'puts(「但是這個......」)'等待第一個'sleep'完成,因爲第一個IO#popen塊正在對'waitpid() '。如果你不想這樣做,那麼你的救援邏輯就需要殺死子進程。 – pilcrow