зеркало из https://github.com/github/ruby.git
* 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
This commit is contained in:
Родитель
5208fec1cf
Коммит
9d77639f30
29
ChangeLog
29
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>
|
||||
|
||||
|
|
12
eval.c
12
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;
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -133,45 +133,51 @@ 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";
|
||||
|
||||
for (;;) {
|
||||
cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
|
||||
st = rb_last_status;
|
||||
if (cpid == -1) return Qnil;
|
||||
|
||||
if (cpid == 0 || cpid == -1)
|
||||
return Qnil;
|
||||
|
||||
#ifdef IF_STOPPED
|
||||
#if defined(IF_STOPPED)
|
||||
if (IF_STOPPED(status)) { /* suspend */
|
||||
state = "stopped";
|
||||
raise_from_wait("stopped", info);
|
||||
}
|
||||
#else
|
||||
#ifdef WIFSTOPPED
|
||||
#elif defined(WIFSTOPPED)
|
||||
if (WIFSTOPPED(status)) { /* suspend */
|
||||
state = "stopped";
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
else {
|
||||
raise_from_wait("exited", info);
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
1
intern.h
1
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));
|
||||
|
|
14
parse.y
14
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($$));
|
||||
|
|
28
process.c
28
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");
|
||||
|
|
7
string.c
7
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче