From: Laurent Sansonetti Date: 2003-05-16T05:55:13+09:00 Subject: PTY: still problems (+patch) Hi all, I just built the lastest ruby distribution from CVS, and noticed that PTY.spawn() does not throw a PTY::ChildExit exception after the process death. I'm running FreeBSD -current. After some pty.c debug, I noticed that pty_finalize_syswait() was called *before* pty_syswait(), thus the thread was killed before it could call rb_waitpid(). Here is a short program I used to remark this problem:: <<---------------------------------------------------------------------- require './pty.so' def myexec(cmd) begin PTY.spawn(cmd) do |r, w, pid| r.each { |line| puts "-> #{line}" } # sleep 1 end rescue PTY::ChildExited => e puts "STATUS: #{e.status}" end end myexec("uname") myexec("ls /does_not_exist") myexec("pleplrpaezlra") -------------------------------------------------------------------->> It produces the following output: -> FreeBSD -> ls: /does_not_exist: No such file or directory Note that if you uncomment the ``sleep 1'' line, PTY.spawn will raise a ChildExited object, which is the expected behaviour: -> FreeBSD STATUS: 0 -> ls: /does_not_exist: No such file or directory STATUS: 256 STATUS: 256 The following patch fixes this issue, by 'joining' the thread instead of killing it: pinux@natalie ~/ruby/ext/pty> cvs diff -u pty.c Index: pty.c =================================================================== RCS file: /src/ruby/ext/pty/pty.c,v retrieving revision 1.15 diff -u -r1.15 pty.c --- pty.c 10 Mar 2003 15:05:18 -0000 1.15 +++ pty.c 15 May 2003 20:24:38 -0000 @@ -299,7 +299,7 @@ pty_finalize_syswait(info) struct pty_info *info; { - rb_thread_kill(info->thread); + rb_funcall(info->thread, rb_intern("join"), 0); rb_detach_process(info->child_pid); return Qnil; } BTW, I saw that rb_thread_join() is private. Perhaps it should be exported, in order to use its 'limit' parameter here. -- Laurent