Es ist am einfachsten in Code zu erklären:Timeout innerhalb eines Popen funktioniert, aber Popen innerhalb eines Timeout nicht?
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
Mein mentales Modell der beiden Blöcke ist identisch:
Also, was bin ich dabei?
bearbeiten: drmaciver schlug auf Twitter vor, dass im ersten Fall, aus irgendeinem Grund, der Rohrsockel in den nicht blockierenden Modus geht, aber in der zweiten nicht. Ich kann mir keinen Grund vorstellen, warum das passieren würde, und ich kann mir auch nicht vorstellen, wie man die Fahnen des Beschreibers bekommt, aber es ist zumindest eine plausible Antwort? An dieser Möglichkeit arbeiten.
Welchen Rubin rennst du? –
Dieses Verhalten tritt bei mindestens 1.8.7 und 1.9.3 auf. jruby blockt für alle 60 auf beiden Blöcken, was das Verhalten ist, das ich a priori erraten hätte. – llimllib
Beachten Sie, dass Ihr 'puts (" but this one ... ")' zwischen den beiden Blöcken für mich _wartet, bis der erste 'sleep' abgeschlossen ist, da der erste IO # popen block pflichtgemäß in einem Aufruf von' waitpid() ist '. Wenn Sie das nicht möchten, muss Ihre Rettungslogik den Kindprozess beenden. – pilcrow