summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-23 04:44:12 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-23 04:44:12 +0000
commit9ec2adf82c2d6e0c114b2d30a6105adf35ca6cad (patch)
tree19528cfeb4b4b350c78a3bfd5a54a68227321e4d /ext
parent9278a97b2b3fdd29f351120e5d9de7db7869124d (diff)
* ext/pty/pty.c: reverts 20326. [ruby-dev:37146].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_1@20333 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/pty/pty.c117
1 files changed, 71 insertions, 46 deletions
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index f0b8e66595..e0d571a581 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -127,8 +127,51 @@ echild_status(VALUE self)
struct pty_info {
int fd;
rb_pid_t child_pid;
+ VALUE thread;
};
+static void
+raise_from_wait(const char *state, const struct pty_info *info)
+{
+ char buf[1024];
+ VALUE exc;
+
+ snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)info->child_pid);
+ exc = rb_exc_new2(eChildExited, buf);
+ rb_iv_set(exc, "status", rb_last_status_get());
+ rb_funcall(info->thread, rb_intern("raise"), 1, exc);
+}
+
+static VALUE
+pty_syswait(void *arg)
+{
+ const struct pty_info *const info = arg;
+ rb_pid_t cpid;
+ int status;
+
+ for (;;) {
+ cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
+ if (cpid == -1) return Qnil;
+
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
+#else
+---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
+#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
+ else if (kill(info->child_pid, 0) == 0) {
+ raise_from_wait("changed", info);
+ }
+ else {
+ raise_from_wait("exited", info);
+ return Qnil;
+ }
+ }
+}
+
static void getDevice(int*, int*, char [DEVICELEN]);
struct exec_info {
@@ -174,6 +217,7 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
}
getDevice(&master, &slave, SlaveName);
+ info->thread = rb_thread_current();
if ((pid = fork()) < 0) {
close(master);
close(slave);
@@ -244,6 +288,15 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
info->fd = master;
}
+static VALUE
+pty_finalize_syswait(struct pty_info *info)
+{
+ rb_thread_kill(info->thread);
+ rb_funcall(info->thread, rb_intern("value"), 0);
+ rb_detach_process(info->child_pid);
+ return Qnil;
+}
+
static int
get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail)
{
@@ -343,19 +396,13 @@ getDevice(int *master, int *slave, char SlaveName[DEVICELEN])
}
}
-static VALUE
-pty_detach_process(struct pty_info *info)
-{
- rb_detach_process(info->child_pid);
- return Qnil;
-}
-
/* ruby function: getpty */
static VALUE
pty_getpty(int argc, VALUE *argv, VALUE self)
{
VALUE res;
struct pty_info info;
+ struct pty_info thinfo;
rb_io_t *wfptr,*rfptr;
VALUE rport = rb_obj_alloc(rb_cFile);
VALUE wport = rb_obj_alloc(rb_cFile);
@@ -379,55 +426,32 @@ pty_getpty(int argc, VALUE *argv, VALUE self)
rb_ary_store(res,1,(VALUE)wport);
rb_ary_store(res,2,PIDT2NUM(info.child_pid));
+ thinfo.thread = rb_thread_create(pty_syswait, (void*)&info);
+ thinfo.child_pid = info.child_pid;
+ rb_thread_schedule();
+
if (rb_block_given_p()) {
- rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info);
+ rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo);
return Qnil;
}
return res;
}
-static void
-raise_from_check(pid_t pid, int status)
+/* ruby function: protect_signal - obsolete */
+static VALUE
+pty_protect(VALUE self)
{
- const char *state;
- char buf[1024];
- VALUE exc;
-
-#if defined(WIFSTOPPED)
-#elif defined(IF_STOPPED)
-#define WIFSTOPPED(status) IF_STOPPED(status)
-#else
----->> Either IF_STOPPED or WIFSTOPPED is needed <<----
-#endif /* WIFSTOPPED | IF_STOPPED */
- if (WIFSTOPPED(status)) { /* suspend */
- state = "stopped";
- }
- else if (kill(pid, 0) == 0) {
- state = "changed";
- }
- else {
- state = "exited";
- }
- snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)pid);
- exc = rb_exc_new2(eChildExited, buf);
- rb_iv_set(exc, "status", rb_last_status_get());
- rb_exc_raise(exc);
+ rb_warn("PTY::protect_signal is no longer needed");
+ rb_yield(Qnil);
+ return self;
}
+/* ruby function: reset_signal - obsolete */
static VALUE
-pty_check(int argc, VALUE *argv, VALUE self)
+pty_reset_signal(VALUE self)
{
- VALUE pid, exc;
- pid_t cpid;
- int status;
-
- rb_scan_args(argc, argv, "11", &pid, &exc);
- cpid = rb_waitpid(NUM2PIDT(pid), &status, WUNTRACED);
- if (cpid == -1) return Qnil;
-
- if (!RTEST(exc)) return status;
- raise_from_check(pid, status);
- return Qnil; /* not reached */
+ rb_warn("PTY::reset_signal is no longer needed");
+ return self;
}
static VALUE cPTY;
@@ -438,7 +462,8 @@ Init_pty()
cPTY = rb_define_module("PTY");
rb_define_module_function(cPTY,"getpty",pty_getpty,-1);
rb_define_module_function(cPTY,"spawn",pty_getpty,-1);
- rb_define_singleton_function(cPTY,"check",pty_check,-1);
+ rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
+ rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
eChildExited = rb_define_class_under(cPTY,"ChildExited",rb_eRuntimeError);
rb_define_method(eChildExited,"status",echild_status,0);