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