Project

General

Profile

Bug #5463 » pty_fail.rb

thinkerbot (Simon Chiang), 10/19/2011 12:04 PM

 
require 'pty'

#############################################################################
# $ ruby --version
# ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0]
# $ ruby pty_no_eof_example.rb 10000
# ..pty_no_eof_example.rb:35:in `block (2 levels) in <main>': timeout waiting for slave EOF (cmd: /bin/bash i:258 pid:37196) (RuntimeError)
# from pty_no_eof_example.rb:23:in `spawn'
# from pty_no_eof_example.rb:23:in `block in <main>'
# from pty_no_eof_example.rb:21:in `upto'
# from pty_no_eof_example.rb:21:in `<main>
#############################################################################
# $ ruby --version
# ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]
# $ ruby pty_no_eof_example.rb 10000
# ....................................................................................................
#############################################################################

max = ARGV.shift || 10000
shell = ARGV.shift || '/bin/bash'
timeout = 3

1.upto(max.to_i) do |i|
exitstatus = nil
PTY.spawn(shell) do |slave, master, pid|
begin

# exit as soon as possible
unless IO.select(nil,[master],nil,timeout)
raise "timeout waiting for master (cmd: #{shell} i:#{i} pid:#{pid})"
end
master.write("exit 8\n")

# read to EOF
while true
unless IO.select([slave],nil,nil,timeout)
raise "timeout waiting for slave EOF (cmd: #{shell} i:#{i} pid:#{pid})"
end

begin
c = slave.read(1)
rescue(Errno::EIO)
c = nil
end

if c.nil?
break
end
end

# Cleanup and capture the exit status to validate the exit worked
Process.wait(pid)
exitstatus = $?.exitstatus

rescue PTY::ChildExited
# Wait can cause a ChildExited error on 1.8.6 and 1.8.7 so handle it as
# a normal exit route. 1.9.2 does not exit this way.
exitstatus = $!.status.exitstatus

rescue Exception
# Cleanup on error - note PTY::ChildExited must be accounted for again
Process.kill(9, pid)
Process.wait(pid) rescue PTY::ChildExited
raise
end
end

unless exitstatus == 8
raise "\nexpected exit status 8 but was #{exitstatus.inspect}"
end

if i % 100 == 0
$stdout.print '.'
$stdout.flush
end
end
puts
(2-2/2)