summaryrefslogtreecommitdiff
path: root/ext/pty
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-03-07 05:59:42 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-03-07 05:59:42 +0000
commit9d77639f30172b0e3b88ea22df0724df61240161 (patch)
tree842fe16738ccff2dee8b962b1ed71ddc0eda62c5 /ext/pty
parent5208fec1cfd93841e0b1a89c42cc2e8692e1aa9c (diff)
* parse.y (dsym): :"symbol string" style should not contain `\0'.
* process.c (proc_detach): new method Proc#detach(pid) which create background watcher thread to issue waitpid. [new] * process.c (rb_detach_process): utility function to detach process from C code. * ext/pty/pty.c (pty_finalize_syswait): terminate watcher thread, and detach child process (by creating new idle waitpid watcher thread). * ext/pty/pty.c (pty_syswait): may lost signal stopped child. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/pty')
-rw-r--r--ext/pty/README40
-rw-r--r--ext/pty/pty.c83
-rw-r--r--ext/pty/script.rb3
3 files changed, 45 insertions, 81 deletions
diff --git a/ext/pty/README b/ext/pty/README
index a09469d..42c7d4f 100644
--- a/ext/pty/README
+++ b/ext/pty/README
@@ -33,43 +33,15 @@ following module fungtions:
the array is passed to the block as block parameters, and the
function itself returns nil.
- While the process spawned by this function is active, SIGCHLD
- is captured to handle the change of the child process. When the
- child process is suspended or finished, an exception is raised.
- As all SIGCHLD signal is captured and processed by PTY module,
- you can't use other function or method which spawns subprosesses
- (including signal() and IO.popen()) while the PTY subprocesses
- are active. Otherwise, unexpected exception will occur. To avoid
- this problem, see protect_signal() below.
-
- If this function is called with an iterator block, SIGCHLD signal
- is captured only within the block. Therefore, it is risky to use
- File objects for PTY subprocess outside the iterator block.
-
+ When the child process is suspended or finished, an exception is
+ raised. If this function is called with an iterator block,
+ exception is raised only within the block. Child process
+ monitor is terminated on block exit.
protect_signal
+ reset_signal
- This function takes an iterator block. Within the iterator block,
- no exception is raised even if any subprocess is terminated.
- This function is used to enable functions like system() or IO.popen()
- while PTY subprocess is active. For example,
-
- PTY.spawn("command_foo") do |r,w|
- ...
- ...
- PTY.protect_signal do
- system "some other commands"
- end
- ...
- end
-
- disables to send exception when "some other commands" is
- terminated.
-
- reset_signal
-
- Disables to handle SIGCHLD while PTY subprocess is active.
-
+ These functions are obsolete in this version of pty.
4. License
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index b7c69fe..f1d4f73 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -133,44 +133,50 @@ struct pty_info {
VALUE thread;
};
+static void
+raise_from_wait(state, info)
+ struct pty_info *info;
+ char *state;
+{
+ extern VALUE rb_last_status;
+ char buf[1024];
+ VALUE exc;
+
+ snprintf(buf, sizeof(buf), "pty - %s: %d", state, info->child_pid);
+ exc = rb_exc_new2(eChildExited, buf);
+ rb_iv_set(exc, "status", rb_last_status);
+ rb_funcall(info->thread, rb_intern("raise"), 1, exc);
+}
+
static VALUE
pty_syswait(info)
struct pty_info *info;
{
- extern VALUE rb_last_status;
int cpid, status;
- char buf[1024];
- VALUE exc, st;
- char *state = "changed";
- cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
- st = rb_last_status;
-
- if (cpid == 0 || cpid == -1)
- return Qnil;
+ for (;;) {
+ cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
+ if (cpid == -1) return Qnil;
-#ifdef IF_STOPPED
- if (IF_STOPPED(status)) { /* suspend */
- state = "stopped";
- }
-#else
-#ifdef WIFSTOPPED
- if (WIFSTOPPED(status)) { /* suspend */
- state = "stopped";
- }
+#if defined(IF_STOPPED)
+ if (IF_STOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
+#elif defined(WIFSTOPPED)
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
-#endif /* WIFSTOPPED */
-#endif /* IF_STOPPED */
- if (WIFEXITED(status)) {
- state = "exit";
+#endif /* WIFSTOPPED | IF_STOPPED */
+ else if (kill(info->child_pid, 0) == 0) {
+ raise_from_wait("changed", info);
+ }
+ else {
+ raise_from_wait("exited", info);
+ return Qnil;
+ }
}
-
- snprintf(buf, sizeof(buf), "pty - %s: %d", state, cpid);
- exc = rb_exc_new2(eChildExited, buf);
- rb_iv_set(exc, "status", st);
- rb_funcall(info->thread, rb_intern("raise"), 1, exc);
- return Qnil;
}
static void getDevice _((int*, int*));
@@ -290,27 +296,14 @@ establishShell(argc, argv, info)
}
static VALUE
-pty_kill_child(info)
+pty_finalize_syswait(info)
struct pty_info *info;
{
- if (rb_funcall(info->thread, rb_intern("alive?"), 0, 0) == Qtrue &&
- kill(info->child_pid, 0) == 0) {
- rb_thread_schedule();
- if (kill(info->child_pid, SIGTERM) == 0) {
- rb_thread_schedule();
- if (kill(info->child_pid, 0) == 0) {
- kill(info->child_pid, SIGINT);
- rb_thread_schedule();
- if (kill(info->child_pid, 0) == 0)
- kill(info->child_pid, SIGKILL);
- }
- }
- }
- rb_funcall(info->thread, rb_intern("join"), 0, 0);
+ rb_thread_kill(info->thread);
+ rb_detach_process(info->child_pid);
return Qnil;
}
-
#ifdef HAVE_OPENPTY
/*
* Use openpty(3) of 4.3BSD Reno and later,
@@ -447,7 +440,7 @@ pty_getpty(argc, argv, self)
thinfo.child_pid = info.child_pid;
if (rb_block_given_p()) {
- rb_ensure(rb_yield, res, pty_kill_child, (VALUE)&thinfo);
+ rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo);
return Qnil;
}
return res;
diff --git a/ext/pty/script.rb b/ext/pty/script.rb
index 3084935..dbb9331 100644
--- a/ext/pty/script.rb
+++ b/ext/pty/script.rb
@@ -10,8 +10,7 @@ logfile = File.open(ofile,"a")
system "stty -echo raw lnext ^_"
-PTY.spawn("/bin/csh") do
- |r_pty,w_pty,pid|
+PTY.spawn("/bin/csh") do |r_pty,w_pty,pid|
Thread.new do
while true