process.c: do not discard status

* process.c (rb_spawn_process): do not discard global escape
  status.  [ruby-core:69304] [Bug #11166]
* process.c (rb_execarg_spawn): extract the start procedure in a
  parent process with ensuring the end procedure.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-05-22 10:42:09 +00:00
Родитель 224172757e
Коммит 46c64caff6
3 изменённых файлов: 61 добавлений и 18 удалений

Просмотреть файл

@ -1,3 +1,11 @@
Fri May 22 19:42:06 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* process.c (rb_spawn_process): do not discard global escape
status. [ruby-core:69304] [Bug #11166]
* process.c (rb_execarg_spawn): extract the start procedure in a
parent process with ensuring the end procedure.
Fri May 22 16:48:32 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* NEWS: added news for net-telnet and rake

Просмотреть файл

@ -2436,8 +2436,8 @@ rb_execarg_parent_start(VALUE execarg_obj)
}
}
void
rb_execarg_parent_end(VALUE execarg_obj)
static VALUE
execarg_parent_end(VALUE execarg_obj)
{
struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
int err = errno;
@ -2461,6 +2461,13 @@ rb_execarg_parent_end(VALUE execarg_obj)
}
errno = err;
return execarg_obj;
}
void
rb_execarg_parent_end(VALUE execarg_obj)
{
execarg_parent_end(execarg_obj);
RB_GC_GUARD(execarg_obj);
}
@ -3845,16 +3852,13 @@ static rb_pid_t
rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
{
rb_pid_t pid;
#if !USE_SPAWNV
int status;
#endif
#if !defined HAVE_WORKING_FORK || USE_SPAWNV
VALUE prog;
struct rb_execarg sarg;
#endif
#if defined HAVE_WORKING_FORK && !USE_SPAWNV
pid = rb_fork_async_signal_safe(&status, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen);
pid = rb_fork_async_signal_safe(NULL, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen);
#else
prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
@ -3892,20 +3896,42 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
return pid;
}
struct spawn_args {
VALUE execarg;
struct {
char *ptr;
size_t buflen;
} errmsg;
};
static VALUE
do_spawn_process(VALUE arg)
{
struct spawn_args *argp = (struct spawn_args *)arg;
rb_execarg_parent_start1(argp->execarg);
return (VALUE)rb_spawn_process(DATA_PTR(argp->execarg),
argp->errmsg.ptr, argp->errmsg.buflen);
}
static rb_pid_t
rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
{
struct spawn_args args;
args.execarg = execarg_obj;
args.errmsg.ptr = errmsg;
args.errmsg.buflen = errmsg_buflen;
return (rb_pid_t)rb_ensure(do_spawn_process, (VALUE)&args,
execarg_parent_end, execarg_obj);
}
static rb_pid_t
rb_spawn_internal(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
{
VALUE execarg_obj;
struct rb_execarg *eargp;
rb_pid_t ret;
execarg_obj = rb_execarg_new(argc, argv, TRUE);
eargp = rb_execarg_get(execarg_obj);
rb_execarg_parent_start(execarg_obj);
ret = rb_spawn_process(eargp, errmsg, errmsg_buflen);
rb_execarg_parent_end(execarg_obj);
RB_GC_GUARD(execarg_obj);
return ret;
return rb_execarg_spawn(execarg_obj, errmsg, errmsg_buflen);
}
rb_pid_t
@ -4267,12 +4293,9 @@ rb_f_spawn(int argc, VALUE *argv)
execarg_obj = rb_execarg_new(argc, argv, TRUE);
eargp = rb_execarg_get(execarg_obj);
rb_execarg_parent_start(execarg_obj);
fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
pid = rb_spawn_process(eargp, errmsg, sizeof(errmsg));
rb_execarg_parent_end(execarg_obj);
RB_GC_GUARD(execarg_obj);
pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
if (pid == -1) {
const char *prog = errmsg;

Просмотреть файл

@ -2017,4 +2017,16 @@ EOS
status = th.value
assert status.success?, status.inspect
end if defined?(fork)
def test_kill_at_spawn_failure
bug11166 = '[ruby-core:69304] [Bug #11166]'
th = nil
x = with_tmpchdir {|d|
prog = "#{d}/notexist"
th = Thread.start {system(prog);sleep}
th.kill
th.join(0.1)
}
assert_equal(th, x)
end if defined?(fork)
end