On Thu, 20 Jul 2006, Reto Schuettel wrote:

> Hi
> 
> Yet another problem/bug I'd like to report.
> 
> On solaris (Solaris 8 tested) multi-processor systems the pty library
> doesn't work properly:


<quote>
require 'test/unit'
require 'pty'

class PTYTester < Test::Unit::TestCase

   def test_sysread
     # execute a command which produces some output and sleep for one second 
     # (to avoid triggering the PTY::ChildExited exception)
     so, si, pid = PTY.spawn("hostname; sleep 1") 
    
     # read some bytes...
     assert_raise(EOFError) do
       puts so.sysread(1)
     end
     # --> throws EOFError 
    
     # well.. lets try again, read again (in same process.. )
     assert_nothing_raised do 
       puts so.sysread(1)
     end
     # --> able to read the first byte
     # When the process gets bound to a single cpu the above code
     # works as expected. 

     # bind the current process to the first cpu 
     assert_nothing_raised do
       system("pbind -b 0 #{$$}")
       so, si, pid = PTY.spawn("hostname; sleep 1") 
       puts so.sysread(1)
     end
     # --> works

   end

   # This snipped starts and stops many processes. To keep on going I ignore
   # any PTY::ChildExited Exceptions[1]. As you can see I kill the process
   # immediately, but usually this would be a normal program termination.
   def test_many_procs_do_no_close
    STDOUT.sync = true
    
    fhs = []
    
   
    assert_raise(Errno::ESRCH) do
      100.times do |i|
        begin
          print "."
          so, si, pid = PTY.spawn("hostname; sleep 1")
        
          sleep 0.1
          Process.kill("TERM", pid)
        rescue PTY::ChildExited => e
          # ignore the exits
        end
      end
    end
   end

   def test_many_procs_and_close
    STDOUT.sync = true
    
    fhs = []
    
   
    assert_raise(Errno::ESRCH) do
      100.times do |i|
        so = nil
        si = nil
        begin
          print "."
          so, si, pid = PTY.spawn("hostname; sleep 1")
        
          sleep 0.1
          Process.kill("TERM", pid)
        rescue PTY::ChildExited => e
          # ignore the exits
        ensure
          si.close if si; si = nil
          so.close if so; so = nil
        end
      end
    end
   end
end

if __FILE__ == $0
  require 'test/unit/ui/console/testrunner'
  Test::Unit::UI::Console::TestRunner.run(PTYTester)
end
</quote>

gives me

brains hgs 323 %> /apps/hgs/RUBY-STABLE-SNAPSHOT-BRAINS/bin/ruby PTY_tests.rb
Loaded suite PTYTester
Started
......................................................................................F................................................................................................FE
Finished in 37.889819 seconds.

  1) Failure:
test_many_procs_and_close(PTYTester) [PTY_tests.rb:66]:
<Errno::ESRCH> exception expected but none was thrown.

  2) Failure:
test_many_procs_do_no_close(PTYTester) [PTY_tests.rb:45]:
<Errno::ESRCH> exception expected but none was thrown.

  3) Error:
test_sysread(PTYTester):
PTY::ChildExited: pty - exited: 20066
    PTY_tests.rb:49:in `test_sysread'

3 tests, 2 assertions, 2 failures, 1 errors
brains hgs 324 %>


on Solaris9.

        Hugh