Najłatwiej wyjaśnić w kodzie:Limit czasu w popen działa, ale popen w limicie czasu nie działa?
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
Moja umysłowy model dwóch bloków jest identyczna:
Więc, co mi brakuje?
edytuj: drmaciver zasugerował na Twitterze, że w pierwszym przypadku z jakiegoś powodu gniazdo rury przechodzi w tryb bez blokowania, ale w drugim nie. Nie mogę wymyślić żadnego powodu, dla którego by to się stało, ani nie mogę wymyślić, jak zdobyć flagi deskryptora, ale jest to przynajmniej wiarygodna odpowiedź? Pracując nad tą możliwością.
Jakiego rubinu używasz? –
to zachowanie występuje co najmniej w wersjach 1.8.7 i 1.9.3. jorkie bloki dla wszystkich 60 na obu blokach, co jest zachowaniem, które bym odgadł a priori. – llimllib
Zauważ, że twoje 'puts (" ale to ... ")' pomiędzy dwoma blokami dla mnie _waits aż do pierwszego 'sleep' jest complete_, ponieważ pierwszy blok popen IO # jest sumiennie w wywołaniu' waitpid() '. Jeśli tego nie chcesz, twoja logika ratunkowa musi zabić proces potomny. – pilcrow