summaryrefslogtreecommitdiff
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
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
-rw-r--r--ChangeLog29
-rw-r--r--eval.c12
-rw-r--r--ext/pty/README40
-rw-r--r--ext/pty/pty.c83
-rw-r--r--ext/pty/script.rb3
-rw-r--r--intern.h1
-rw-r--r--parse.y14
-rw-r--r--process.c28
-rw-r--r--string.c9
9 files changed, 119 insertions, 100 deletions
diff --git a/ChangeLog b/ChangeLog
index d81ef4c335..6ab050bc2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,38 @@
+Fri Mar 7 03:31:36 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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.
+
Fri Mar 7 00:30:33 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/Win32API/Win32API.c: no longer use inline-asms.
* ext/Win32API/extconf.rb: no need to add gcc options.
+Thu Mar 6 13:02:10 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (reswords): fix reswords list.
+
Wed Mar 5 12:13:21 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* configure.in: better YACC support on HP-UX.
+Wed Mar 5 05:55:20 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_cat): remove ptr NULL check and MEMZERO(). ptr
+ must be non NULL.
+
Tue Mar 04 23:12:07 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* configure.in, bcc32/Makefile.sub, win32/Makefile.sub: define
@@ -21,10 +46,10 @@ Tue Mar 04 23:12:07 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
Tue Mar 4 17:54:30 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
- * array.c (rb_ary_aref): give warning if index is a symbol.
+ * array.c (rb_ary_aref): raise TypeError if index is a symbol.
[ruby-list:37217]
- * array.c (rb_ary_aset): raise TypeError if index is a symbol.
+ * array.c (rb_ary_aset): ditto.
Tue Nov 13 14:39:11 2001 WATANABE Tetsuya <tetsu@jpn.hp.com>
diff --git a/eval.c b/eval.c
index 17f7f774f3..7dbc4d7ab8 100644
--- a/eval.c
+++ b/eval.c
@@ -4024,17 +4024,19 @@ massign(self, node, val, pcall)
int pcall;
{
NODE *list;
+ VALUE tmp;
long i = 0, len;
len = RARRAY(val)->len;
list = node->nd_head;
- if (len == 1 && list) {
+ if (len == 1 && list && (list->nd_next || node->nd_args)) {
VALUE v = RARRAY(val)->ptr[0];
- VALUE tmp = rb_check_array_type(v);
+ tmp = rb_check_array_type(v);
if (NIL_P(tmp)) {
assign(self, list->nd_head, v, pcall);
list = list->nd_next;
+ i = 1;
}
else {
len = RARRAY(tmp)->len;
@@ -4043,13 +4045,13 @@ massign(self, node, val, pcall)
list = list->nd_next;
}
}
- i = 1;
}
else {
for (; list && i<len; i++) {
assign(self, list->nd_head, RARRAY(val)->ptr[i], pcall);
list = list->nd_next;
}
+ tmp = val;
}
if (pcall && list) goto arg_error;
if (node->nd_args) {
@@ -4057,7 +4059,7 @@ massign(self, node, val, pcall)
/* no check for mere `*' */
}
else if (!list && i<len) {
- assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i), pcall);
+ assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(tmp)->ptr+i), pcall);
}
else {
assign(self, node->nd_args, rb_ary_new2(0), pcall);
@@ -8640,7 +8642,7 @@ rb_thread_run(thread)
return thread;
}
-static VALUE
+VALUE
rb_thread_kill(thread)
VALUE thread;
{
diff --git a/ext/pty/README b/ext/pty/README
index a09469d39c..42c7d4f891 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 b7c69fe400..f1d4f73a18 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 3084935637..dbb933171f 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
diff --git a/intern.h b/intern.h
index a53a9a92d4..e1872938b8 100644
--- a/intern.h
+++ b/intern.h
@@ -199,6 +199,7 @@ void rb_thread_sleep_forever _((void));
VALUE rb_thread_stop _((void));
VALUE rb_thread_wakeup _((VALUE));
VALUE rb_thread_run _((VALUE));
+VALUE rb_thread_kill _((VALUE));
VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*));
void rb_thread_interrupt _((void));
void rb_thread_trap_eval _((VALUE, int));
diff --git a/parse.y b/parse.y
index c1e75b3fb1..1ee5633042 100644
--- a/parse.y
+++ b/parse.y
@@ -924,9 +924,10 @@ op : '|' { $$ = '|'; }
reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
| kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
| kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
- | kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
+ | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
| kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
| kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
+ | kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
;
arg : lhs '=' arg
@@ -2095,13 +2096,16 @@ dsym : tSYMBEG xstring_contents tSTRING_END
}
else {
switch (nd_type($$)) {
- case NODE_STR:
- $$->nd_lit = ID2SYM(rb_intern(RSTRING($$->nd_lit)->ptr));
- nd_set_type($$, NODE_LIT);
- break;
case NODE_DSTR:
nd_set_type($$, NODE_DSYM);
break;
+ case NODE_STR:
+ if (strlen(RSTRING($$->nd_lit)->ptr) == RSTRING($$->nd_lit)->len) {
+ $$->nd_lit = ID2SYM(rb_intern(RSTRING($$->nd_lit)->ptr));
+ nd_set_type($$, NODE_LIT);
+ break;
+ }
+ /* fall through */
default:
$$ = rb_node_newnode(NODE_DSYM, rb_str_new(0, 0),
1, NEW_LIST($$));
diff --git a/process.c b/process.c
index 38cdfb0964..3fc7f9e065 100644
--- a/process.c
+++ b/process.c
@@ -411,6 +411,33 @@ proc_waitall()
return result;
}
+static VALUE
+detach_process_watcer(pid_p)
+ int *pid_p;
+{
+ int cpid, status;
+
+ for (;;) {
+ cpid = rb_waitpid(*pid_p, &status, WNOHANG);
+ if (cpid == -1) return Qnil;
+ rb_thread_sleep(1);
+ }
+}
+
+void
+rb_detach_process(pid)
+ int pid;
+{
+ rb_thread_create(detach_process_watcer, (void*)&pid);
+}
+
+static VALUE
+proc_detach(obj, pid)
+ VALUE pid;
+{
+ rb_detach_process(NUM2INT(pid));
+}
+
#ifndef HAVE_STRING_H
char *strtok();
#endif
@@ -1319,6 +1346,7 @@ Init_process()
rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
+ rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
rb_cProcStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
rb_undef_method(CLASS_OF(rb_cProcStatus), "new");
diff --git a/string.c b/string.c
index e4308be0f5..a273400d89 100644
--- a/string.c
+++ b/string.c
@@ -614,12 +614,7 @@ rb_str_cat(str, ptr, len)
if (FL_TEST(str, STR_ASSOC)) {
rb_str_modify(str);
REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
- if (ptr) {
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
- }
- else {
- MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, len);
- }
+ memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
RSTRING(str)->len += len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
return str;
@@ -3076,7 +3071,7 @@ rb_str_intern(str)
rb_raise(rb_eArgError, "interning empty string");
}
if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
- rb_raise(rb_eArgError, "string contains `\\0'");
+ rb_raise(rb_eArgError, "symbol string may not contain `\\0'");
id = rb_intern(RSTRING(str)->ptr);
return ID2SYM(id);
}