这是最简单的代码来解释:在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