Bug #5487

popen3 + timeout regression in ruby 1.9

Added by William Morgan over 3 years ago. Updated 12 months ago.

[ruby-core:40419]
Status:Rejected
Priority:Normal
Assignee:Akira Tanaka
ruby -v:1.9.2p290 Backport:

Description

Wrapping Open3.popen3 in a Timeout::timeout block used to work in Ruby 1.8, but doesn't work in 1.9:

w@masanjin:~$ cat timeout.rb
require 'timeout'
require 'open3'

Timeout::timeout(1) { Open3.popen3("sleep 100 && echo hi") { |i, o, e| e.read } }
w@masanjin:~$ /usr/bin/ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
w@masanjin:~$ /usr/bin/ruby timeout.rb
/usr/lib/ruby/1.8/timeout.rb:60: execution expired (Timeout::Error)
from /usr/lib/ruby/1.8/open3.rb:86:in `popen3'
from timeout.rb:4
from timeout.rb:4

w@masanjin:~$ ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]
w@masanjin:~$ ruby timeout.rb
[sleeps forever]

History

#1 Updated by Eric Wong over 3 years ago

William Morgan wmorgan-redmine@masanjin.net wrote:

Bug #5487: popen3 + timeout regression in ruby 1.9
http://redmine.ruby-lang.org/issues/5487

Wrapping Open3.popen3 in a Timeout::timeout block used to work in Ruby 1.8, but doesn't work in 1.9:

I think this is related to http://redmine.ruby-lang.org/issues/4681
I provided an explanation (but no fix) there.

#2 Updated by mathew murphy over 3 years ago

In case it helps, I have a Gist with some working 1.9.3 code to perform a popen3 with time out, not using Timeout::timeout:

https://gist.github.com/1032297

#3 Updated by Koichi Sasada about 3 years ago

  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to Akira Tanaka

#4 Updated by Akira Tanaka 12 months ago

  • Status changed from Assigned to Rejected

Please avoid Timeout.
Even if it doesn't hang as Ruby 1.8, it doesn't clean child processes.

Thread#join's argument (timeout) is usable to implement to timeout.

Open3.popen3("sleep 100 && echo hi", :pgroup=>true) {|i, o, e, w|
  th = Thread.new { e.read }
  if !w.join(1) # wait thread does not end within 1 second? 
    Process.kill(:TERM, -w.pid) # kill the process group
  end
  p th.value
}

Also available in: Atom PDF