зеркало из https://github.com/github/ruby.git
* process.c (rb_fork): propagete an error message from child to parent.
(rb_f_exec): show details of error in child process on exception. (save_redirect_fd): add error message arguments. (run_exec_dup2): ditto. (run_exec_close): ditto. (run_exec_open): ditto. (run_exec_dup2_child): ditto. (run_exec_pgroup): ditto. (run_exec_rlimit): ditto. (rb_run_exec_options): ditto. (rb_exec): ditto. (rb_exec_atfork): ditto. (rb_spawn_internal): ditto. (rb_spawn): ditto. (rb_f_system): follow arguments change. (proc_daemon): ditto. (rb_f_spawn): show details of error in child process on exception. * io.c (popen_exec): add error message arguments. (pipe_open): show details of error in child process on exception. * include/ruby/intern.h (rb_run_exec_options): add error message arguments. (rb_exec): ditto. (rb_fork): ditto. (rb_spawn): ditto. * ext/pty/pty.c (chfunc): add error message arguments. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
5677106ec9
Коммит
423bbf80d5
32
ChangeLog
32
ChangeLog
|
@ -1,3 +1,35 @@
|
|||
Tue Dec 23 21:55:05 2008 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* process.c (rb_fork): propagete an error message from child to parent.
|
||||
(rb_f_exec): show details of error in child process on
|
||||
exception.
|
||||
(save_redirect_fd): add error message arguments.
|
||||
(run_exec_dup2): ditto.
|
||||
(run_exec_close): ditto.
|
||||
(run_exec_open): ditto.
|
||||
(run_exec_dup2_child): ditto.
|
||||
(run_exec_pgroup): ditto.
|
||||
(run_exec_rlimit): ditto.
|
||||
(rb_run_exec_options): ditto.
|
||||
(rb_exec): ditto.
|
||||
(rb_exec_atfork): ditto.
|
||||
(rb_spawn_internal): ditto.
|
||||
(rb_spawn): ditto.
|
||||
(rb_f_system): follow arguments change.
|
||||
(proc_daemon): ditto.
|
||||
(rb_f_spawn): show details of error in child process on exception.
|
||||
|
||||
* io.c (popen_exec): add error message arguments.
|
||||
(pipe_open): show details of error in child process on exception.
|
||||
|
||||
* include/ruby/intern.h (rb_run_exec_options): add error message
|
||||
arguments.
|
||||
(rb_exec): ditto.
|
||||
(rb_fork): ditto.
|
||||
(rb_spawn): ditto.
|
||||
|
||||
* ext/pty/pty.c (chfunc): add error message arguments.
|
||||
|
||||
Tue Dec 23 20:28:28 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
||||
|
||||
* io.c: rdoc for File::open and 1.9 feature in file modes.
|
||||
|
|
|
@ -155,7 +155,7 @@ struct child_info {
|
|||
};
|
||||
|
||||
static int
|
||||
chfunc(void *data)
|
||||
chfunc(void *data, char *errmsg, size_t errmsg_len)
|
||||
{
|
||||
struct child_info *carg = data;
|
||||
int master = carg->master;
|
||||
|
@ -258,7 +258,7 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
|
|||
carg.slavename = SlaveName;
|
||||
carg.argc = argc;
|
||||
carg.argv = argv;
|
||||
pid = rb_fork(0, chfunc, &carg, Qnil);
|
||||
pid = rb_fork(0, chfunc, &carg, Qnil, NULL, 0);
|
||||
|
||||
if (pid < 0) {
|
||||
close(master);
|
||||
|
|
|
@ -472,13 +472,13 @@ int rb_proc_exec(const char*);
|
|||
VALUE rb_exec_arg_init(int argc, VALUE *argv, int accept_shell, struct rb_exec_arg *e);
|
||||
int rb_exec_arg_addopt(struct rb_exec_arg *e, VALUE key, VALUE val);
|
||||
void rb_exec_arg_fixup(struct rb_exec_arg *e);
|
||||
int rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s);
|
||||
int rb_exec(const struct rb_exec_arg*);
|
||||
rb_pid_t rb_fork(int*, int (*)(void*), void*, VALUE);
|
||||
int rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s, char*, size_t);
|
||||
int rb_exec(const struct rb_exec_arg*, char*, size_t);
|
||||
rb_pid_t rb_fork(int*, int (*)(void*, char*, size_t), void*, VALUE, char*, size_t);
|
||||
VALUE rb_f_exec(int,VALUE*);
|
||||
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags);
|
||||
void rb_syswait(rb_pid_t pid);
|
||||
rb_pid_t rb_spawn(int, VALUE*);
|
||||
rb_pid_t rb_spawn(int, VALUE*, char*, size_t);
|
||||
VALUE rb_proc_times(VALUE);
|
||||
VALUE rb_detach_process(rb_pid_t pid);
|
||||
/* range.c */
|
||||
|
|
21
io.c
21
io.c
|
@ -4440,12 +4440,12 @@ rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
|
|||
}
|
||||
|
||||
static int
|
||||
popen_exec(void *pp)
|
||||
popen_exec(void *pp, char *errmsg, size_t errmsg_len)
|
||||
{
|
||||
struct popen_arg *p = (struct popen_arg*)pp;
|
||||
|
||||
rb_thread_atfork_before_exec();
|
||||
return rb_exec(p->execp);
|
||||
return rb_exec(p->execp, errmsg, errmsg_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4460,6 +4460,7 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
#if defined(HAVE_FORK)
|
||||
int status;
|
||||
struct popen_arg arg;
|
||||
char errmsg[80] = { '\0' };
|
||||
#elif defined(_WIN32)
|
||||
volatile VALUE argbuf;
|
||||
char **args = NULL;
|
||||
|
@ -4530,11 +4531,11 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
}
|
||||
if (eargp) {
|
||||
rb_exec_arg_fixup(arg.execp);
|
||||
pid = rb_fork(&status, popen_exec, &arg, arg.execp->redirect_fds);
|
||||
pid = rb_fork(&status, popen_exec, &arg, arg.execp->redirect_fds, errmsg, sizeof(errmsg));
|
||||
}
|
||||
else {
|
||||
fflush(stdin); /* is it really needed? */
|
||||
pid = rb_fork(&status, 0, 0, Qnil);
|
||||
pid = rb_fork(&status, 0, 0, Qnil, NULL, 0);
|
||||
if (pid == 0) { /* child */
|
||||
popen_redirect(&arg);
|
||||
rb_io_synchronized(RFILE(orig_stdout)->fptr);
|
||||
|
@ -4553,6 +4554,8 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
close(arg.write_pair[1]);
|
||||
}
|
||||
errno = e;
|
||||
if (errmsg[0])
|
||||
rb_sys_fail(errmsg);
|
||||
rb_sys_fail(cmd);
|
||||
}
|
||||
if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
|
||||
|
@ -4616,7 +4619,7 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
}
|
||||
if (eargp) {
|
||||
rb_exec_arg_fixup(eargp);
|
||||
rb_run_exec_options(eargp, &sarg);
|
||||
rb_run_exec_options(eargp, &sarg, NULL, 0);
|
||||
}
|
||||
while ((pid = (args ?
|
||||
rb_w32_aspawn(P_NOWAIT, 0, args) :
|
||||
|
@ -4631,13 +4634,13 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
break;
|
||||
default:
|
||||
if (eargp)
|
||||
rb_run_exec_options(&sarg, NULL);
|
||||
rb_run_exec_options(&sarg, NULL, NULL, 0);
|
||||
rb_sys_fail(cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (eargp)
|
||||
rb_run_exec_options(&sarg, NULL);
|
||||
rb_run_exec_options(&sarg, NULL, NULL, 0);
|
||||
if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
|
||||
close(pair[1]);
|
||||
fd = pair[0];
|
||||
|
@ -4659,11 +4662,11 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
}
|
||||
if (eargp) {
|
||||
rb_exec_arg_fixup(eargp);
|
||||
rb_run_exec_options(eargp, &sarg);
|
||||
rb_run_exec_options(eargp, &sarg, NULL, 0);
|
||||
}
|
||||
fp = popen(cmd, modestr);
|
||||
if (eargp)
|
||||
rb_run_exec_options(&sarg, NULL);
|
||||
rb_run_exec_options(&sarg, NULL, NULL, 0);
|
||||
if (!fp) rb_sys_fail(RSTRING_PTR(prog));
|
||||
fd = fileno(fp);
|
||||
#endif
|
||||
|
|
173
process.c
173
process.c
|
@ -1756,17 +1756,23 @@ VALUE
|
|||
rb_f_exec(int argc, VALUE *argv)
|
||||
{
|
||||
struct rb_exec_arg earg;
|
||||
#define CHILD_ERRMSG_BUFLEN 80
|
||||
char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
|
||||
|
||||
rb_exec_arg_init(argc, argv, Qtrue, &earg);
|
||||
if (NIL_P(rb_ary_entry(earg.options, EXEC_OPTION_CLOSE_OTHERS)))
|
||||
rb_exec_arg_addopt(&earg, ID2SYM(rb_intern("close_others")), Qfalse);
|
||||
rb_exec_arg_fixup(&earg);
|
||||
|
||||
rb_exec(&earg);
|
||||
rb_exec(&earg, errmsg, sizeof(errmsg));
|
||||
if (errmsg[0])
|
||||
rb_sys_fail(errmsg);
|
||||
rb_sys_fail(earg.prog);
|
||||
return Qnil; /* dummy */
|
||||
}
|
||||
|
||||
#define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
|
||||
|
||||
/*#define DEBUG_REDIRECT*/
|
||||
#if defined(DEBUG_REDIRECT)
|
||||
|
||||
|
@ -1837,12 +1843,15 @@ redirect_open(const char *pathname, int flags, mode_t perm)
|
|||
#endif
|
||||
|
||||
static int
|
||||
save_redirect_fd(int fd, VALUE save)
|
||||
save_redirect_fd(int fd, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
if (!NIL_P(save)) {
|
||||
VALUE newary;
|
||||
int save_fd = redirect_dup(fd);
|
||||
if (save_fd == -1) return -1;
|
||||
if (save_fd == -1) {
|
||||
ERRMSG("dup");
|
||||
return -1;
|
||||
}
|
||||
newary = rb_ary_entry(save, EXEC_OPTION_DUP2);
|
||||
if (NIL_P(newary)) {
|
||||
newary = hide_obj(rb_ary_new());
|
||||
|
@ -1897,7 +1906,7 @@ intrcmp(const void *a, const void *b)
|
|||
}
|
||||
|
||||
static int
|
||||
run_exec_dup2(VALUE ary, VALUE save)
|
||||
run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int n, i;
|
||||
int ret;
|
||||
|
@ -1910,7 +1919,11 @@ run_exec_dup2(VALUE ary, VALUE save)
|
|||
} *pairs = 0;
|
||||
|
||||
n = RARRAY_LEN(ary);
|
||||
pairs = ALLOC_N(struct fd_pair, n);
|
||||
pairs = (struct fd_pair *)malloc(sizeof(struct fd_pair) * n);
|
||||
if (pairs == NULL) {
|
||||
ERRMSG("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialize oldfd and newfd: O(n) */
|
||||
for (i = 0; i < n; i++) {
|
||||
|
@ -1948,11 +1961,13 @@ run_exec_dup2(VALUE ary, VALUE save)
|
|||
for (i = 0; i < n; i++) {
|
||||
int j = i;
|
||||
while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
|
||||
if (save_redirect_fd(pairs[j].newfd, save) < 0)
|
||||
if (save_redirect_fd(pairs[j].newfd, save, errmsg, errmsg_buflen) < 0)
|
||||
goto fail;
|
||||
ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("dup2");
|
||||
goto fail;
|
||||
}
|
||||
pairs[j].oldfd = -1;
|
||||
j = pairs[j].older_index;
|
||||
if (j != -1)
|
||||
|
@ -1969,13 +1984,17 @@ run_exec_dup2(VALUE ary, VALUE save)
|
|||
#ifdef F_GETFD
|
||||
int fd = pairs[i].oldfd;
|
||||
ret = fcntl(fd, F_GETFD);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("fcntl(F_GETFD)");
|
||||
goto fail;
|
||||
}
|
||||
if (ret & FD_CLOEXEC) {
|
||||
ret &= ~FD_CLOEXEC;
|
||||
ret = fcntl(fd, F_SETFD, ret);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("fcntl(F_SETFD)");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pairs[i].oldfd = -1;
|
||||
|
@ -1983,29 +2002,37 @@ run_exec_dup2(VALUE ary, VALUE save)
|
|||
}
|
||||
if (extra_fd == -1) {
|
||||
extra_fd = redirect_dup(pairs[i].oldfd);
|
||||
if (extra_fd == -1)
|
||||
if (extra_fd == -1) {
|
||||
ERRMSG("dup");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = redirect_dup2(pairs[i].oldfd, extra_fd);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("dup2");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
pairs[i].oldfd = extra_fd;
|
||||
j = pairs[i].older_index;
|
||||
pairs[i].older_index = -1;
|
||||
while (j != -1) {
|
||||
ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("dup2");
|
||||
goto fail;
|
||||
}
|
||||
pairs[j].oldfd = -1;
|
||||
j = pairs[j].older_index;
|
||||
}
|
||||
}
|
||||
if (extra_fd != -1) {
|
||||
ret = redirect_close(extra_fd);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("close");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
xfree(pairs);
|
||||
|
@ -2017,7 +2044,7 @@ run_exec_dup2(VALUE ary, VALUE save)
|
|||
}
|
||||
|
||||
static int
|
||||
run_exec_close(VALUE ary)
|
||||
run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
|
@ -2025,14 +2052,16 @@ run_exec_close(VALUE ary)
|
|||
VALUE elt = RARRAY_PTR(ary)[i];
|
||||
int fd = FIX2INT(RARRAY_PTR(elt)[0]);
|
||||
ret = redirect_close(fd);
|
||||
if (ret == -1)
|
||||
if (ret == -1) {
|
||||
ERRMSG("close");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
run_exec_open(VALUE ary, VALUE save)
|
||||
run_exec_open(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
|
@ -2045,7 +2074,10 @@ run_exec_open(VALUE ary, VALUE save)
|
|||
int perm = NUM2INT(RARRAY_PTR(param)[2]);
|
||||
int need_close = 1;
|
||||
int fd2 = redirect_open(path, flags, perm);
|
||||
if (fd2 == -1) return -1;
|
||||
if (fd2 == -1) {
|
||||
ERRMSG("open");
|
||||
return -1;
|
||||
}
|
||||
while (i < RARRAY_LEN(ary) &&
|
||||
(elt = RARRAY_PTR(ary)[i], RARRAY_PTR(elt)[1] == param)) {
|
||||
fd = FIX2INT(RARRAY_PTR(elt)[0]);
|
||||
|
@ -2053,23 +2085,29 @@ run_exec_open(VALUE ary, VALUE save)
|
|||
need_close = 0;
|
||||
}
|
||||
else {
|
||||
if (save_redirect_fd(fd, save) < 0)
|
||||
if (save_redirect_fd(fd, save, errmsg, errmsg_buflen) < 0)
|
||||
return -1;
|
||||
ret = redirect_dup2(fd2, fd);
|
||||
if (ret == -1) return -1;
|
||||
if (ret == -1) {
|
||||
ERRMSG("dup2");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (need_close) {
|
||||
ret = redirect_close(fd2);
|
||||
if (ret == -1) return -1;
|
||||
if (ret == -1) {
|
||||
ERRMSG("close");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
run_exec_dup2_child(VALUE ary, VALUE save)
|
||||
run_exec_dup2_child(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int i, ret;
|
||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||
|
@ -2077,17 +2115,20 @@ run_exec_dup2_child(VALUE ary, VALUE save)
|
|||
int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
|
||||
int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
|
||||
|
||||
if (save_redirect_fd(newfd, save) < 0)
|
||||
if (save_redirect_fd(newfd, save, errmsg, errmsg_buflen) < 0)
|
||||
return -1;
|
||||
ret = redirect_dup2(oldfd, newfd);
|
||||
if (ret == -1) return -1;
|
||||
if (ret == -1) {
|
||||
ERRMSG("dup2");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETPGID
|
||||
static int
|
||||
run_exec_pgroup(VALUE obj, VALUE save)
|
||||
run_exec_pgroup(VALUE obj, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
/*
|
||||
* If FD_CLOEXEC is available, rb_fork waits the child's execve.
|
||||
|
@ -2095,6 +2136,7 @@ run_exec_pgroup(VALUE obj, VALUE save)
|
|||
* No race condition, even without setpgid from the parent.
|
||||
* (Is there an environment which has setpgid but FD_CLOEXEC?)
|
||||
*/
|
||||
int ret;
|
||||
pid_t pgroup;
|
||||
if (!NIL_P(save)) {
|
||||
/* maybe meaningless with no fork environment... */
|
||||
|
@ -2104,13 +2146,15 @@ run_exec_pgroup(VALUE obj, VALUE save)
|
|||
if (pgroup == 0) {
|
||||
pgroup = getpid();
|
||||
}
|
||||
return setpgid(getpid(), pgroup);
|
||||
ret = setpgid(getpid(), pgroup);
|
||||
if (ret == -1) ERRMSG("setpgid");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RLIM2NUM
|
||||
static int
|
||||
run_exec_rlimit(VALUE ary, VALUE save)
|
||||
run_exec_rlimit(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||
|
@ -2119,8 +2163,10 @@ run_exec_rlimit(VALUE ary, VALUE save)
|
|||
struct rlimit rlim;
|
||||
if (!NIL_P(save)) {
|
||||
VALUE tmp, newary;
|
||||
if (getrlimit(rtype, &rlim) == -1)
|
||||
if (getrlimit(rtype, &rlim) == -1) {
|
||||
ERRMSG("getrlimit");
|
||||
return -1;
|
||||
}
|
||||
tmp = hide_obj(rb_ary_new3(3, RARRAY_PTR(elt)[0],
|
||||
RLIM2NUM(rlim.rlim_cur),
|
||||
RLIM2NUM(rlim.rlim_max)));
|
||||
|
@ -2133,15 +2179,17 @@ run_exec_rlimit(VALUE ary, VALUE save)
|
|||
}
|
||||
rlim.rlim_cur = NUM2RLIM(RARRAY_PTR(elt)[1]);
|
||||
rlim.rlim_max = NUM2RLIM(RARRAY_PTR(elt)[2]);
|
||||
if (setrlimit(rtype, &rlim) == -1)
|
||||
if (setrlimit(rtype, &rlim) == -1) {
|
||||
ERRMSG("setrlimit");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
||||
rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
VALUE options = e->options;
|
||||
VALUE soptions = Qnil;
|
||||
|
@ -2161,7 +2209,7 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
#ifdef HAVE_SETPGID
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_PGROUP);
|
||||
if (RTEST(obj)) {
|
||||
if (run_exec_pgroup(obj, soptions) == -1)
|
||||
if (run_exec_pgroup(obj, soptions, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
@ -2169,7 +2217,7 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
#ifdef RLIM2NUM
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
|
||||
if (!NIL_P(obj)) {
|
||||
if (run_exec_rlimit(obj, soptions) == -1)
|
||||
if (run_exec_rlimit(obj, soptions, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
@ -2203,8 +2251,10 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
hide_obj(rb_str_new2(cwd)));
|
||||
xfree(cwd);
|
||||
}
|
||||
if (chdir(RSTRING_PTR(obj)) == -1)
|
||||
if (chdir(RSTRING_PTR(obj)) == -1) {
|
||||
ERRMSG("chdir");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_UMASK);
|
||||
|
@ -2217,7 +2267,7 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
|
||||
if (!NIL_P(obj)) {
|
||||
if (run_exec_dup2(obj, soptions) == -1)
|
||||
if (run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2226,7 +2276,7 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
if (!NIL_P(soptions))
|
||||
rb_warn("cannot close fd before spawn");
|
||||
else {
|
||||
if (run_exec_close(obj) == -1)
|
||||
if (run_exec_close(obj, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -2240,13 +2290,13 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_OPEN);
|
||||
if (!NIL_P(obj)) {
|
||||
if (run_exec_open(obj, soptions) == -1)
|
||||
if (run_exec_open(obj, soptions, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
obj = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
|
||||
if (!NIL_P(obj)) {
|
||||
if (run_exec_dup2_child(obj, soptions) == -1)
|
||||
if (run_exec_dup2_child(obj, soptions, errmsg, errmsg_buflen) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2254,13 +2304,13 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
|||
}
|
||||
|
||||
int
|
||||
rb_exec(const struct rb_exec_arg *e)
|
||||
rb_exec(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
int argc = e->argc;
|
||||
VALUE *argv = e->argv;
|
||||
const char *prog = e->prog;
|
||||
|
||||
if (rb_run_exec_options(e, NULL) < 0) {
|
||||
if (rb_run_exec_options(e, NULL, errmsg, errmsg_buflen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2281,10 +2331,10 @@ rb_exec(const struct rb_exec_arg *e)
|
|||
|
||||
#ifdef HAVE_FORK
|
||||
static int
|
||||
rb_exec_atfork(void* arg)
|
||||
rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
rb_thread_atfork_before_exec();
|
||||
return rb_exec(arg);
|
||||
return rb_exec(arg, errmsg, errmsg_buflen);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2367,7 +2417,8 @@ pipe_nocrash(int filedes[2], VALUE fds)
|
|||
* +chfunc+ must not raise any exceptions.
|
||||
*/
|
||||
rb_pid_t
|
||||
rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
|
||||
rb_fork(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
|
||||
char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
rb_pid_t pid;
|
||||
int err, state = 0;
|
||||
|
@ -2422,10 +2473,12 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
|
|||
#ifdef FD_CLOEXEC
|
||||
close(ep[0]);
|
||||
#endif
|
||||
if (!(*chfunc)(charg)) _exit(EXIT_SUCCESS);
|
||||
if (!(*chfunc)(charg, errmsg, errmsg_buflen)) _exit(EXIT_SUCCESS);
|
||||
#ifdef FD_CLOEXEC
|
||||
err = errno;
|
||||
write(ep[1], &err, sizeof(err));
|
||||
errmsg[errmsg_buflen-1] = '\0';
|
||||
write(ep[1], errmsg, strlen(errmsg));
|
||||
#endif
|
||||
#if EXIT_SUCCESS == 127
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -2441,6 +2494,14 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
|
|||
if ((state = read(ep[0], &err, sizeof(err))) < 0) {
|
||||
err = errno;
|
||||
}
|
||||
if (state == sizeof(err) &&
|
||||
errmsg && 0 < errmsg_buflen) {
|
||||
ssize_t ret;
|
||||
ret = read(ep[0], errmsg, errmsg_buflen-1);
|
||||
if (0 <= ret) {
|
||||
errmsg[ret] = '\0';
|
||||
}
|
||||
}
|
||||
close(ep[0]);
|
||||
if (state) {
|
||||
if (status) {
|
||||
|
@ -2487,7 +2548,7 @@ rb_f_fork(VALUE obj)
|
|||
|
||||
rb_secure(2);
|
||||
|
||||
switch (pid = rb_fork(0, 0, 0, Qnil)) {
|
||||
switch (pid = rb_fork(0, 0, 0, Qnil, NULL, 0)) {
|
||||
case 0:
|
||||
#ifdef linux
|
||||
after_exec();
|
||||
|
@ -2725,7 +2786,8 @@ rb_syswait(rb_pid_t pid)
|
|||
}
|
||||
|
||||
static rb_pid_t
|
||||
rb_spawn_internal(int argc, VALUE *argv, int default_close_others)
|
||||
rb_spawn_internal(int argc, VALUE *argv, int default_close_others,
|
||||
char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
rb_pid_t status;
|
||||
VALUE prog;
|
||||
|
@ -2742,10 +2804,10 @@ rb_spawn_internal(int argc, VALUE *argv, int default_close_others)
|
|||
rb_exec_arg_fixup(&earg);
|
||||
|
||||
#if defined HAVE_FORK
|
||||
status = rb_fork(&status, rb_exec_atfork, &earg, earg.redirect_fds);
|
||||
status = rb_fork(&status, rb_exec_atfork, &earg, earg.redirect_fds, errmsg, errmsg_buflen);
|
||||
if (prog && earg.argc) earg.argv[0] = prog;
|
||||
#else
|
||||
if (rb_run_exec_options(&earg, &sarg) < 0) {
|
||||
if (rb_run_exec_options(&earg, &sarg, errmsg, errmsg_buflen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2769,15 +2831,15 @@ rb_spawn_internal(int argc, VALUE *argv, int default_close_others)
|
|||
rb_last_status_set((status & 0xff) << 8, 0);
|
||||
# endif
|
||||
|
||||
rb_run_exec_options(&sarg, NULL);
|
||||
rb_run_exec_options(&sarg, NULL, errmsg, errmsg_buflen);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
rb_pid_t
|
||||
rb_spawn(int argc, VALUE *argv)
|
||||
rb_spawn(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
|
||||
{
|
||||
return rb_spawn_internal(argc, argv, Qtrue);
|
||||
return rb_spawn_internal(argc, argv, Qtrue, errmsg, errmsg_buflen);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2825,7 +2887,7 @@ rb_f_system(int argc, VALUE *argv)
|
|||
|
||||
chfunc = signal(SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
status = rb_spawn_internal(argc, argv, Qfalse);
|
||||
status = rb_spawn_internal(argc, argv, Qfalse, NULL, 0);
|
||||
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
|
||||
if (status > 0) {
|
||||
rb_syswait(status);
|
||||
|
@ -3068,9 +3130,14 @@ static VALUE
|
|||
rb_f_spawn(int argc, VALUE *argv)
|
||||
{
|
||||
rb_pid_t pid;
|
||||
char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
|
||||
|
||||
pid = rb_spawn(argc, argv);
|
||||
if (pid == -1) rb_sys_fail(RSTRING_PTR(argv[0]));
|
||||
pid = rb_spawn(argc, argv, errmsg, sizeof(errmsg));
|
||||
if (pid == -1) {
|
||||
if (errmsg[0] == '\0')
|
||||
rb_sys_fail(RSTRING_PTR(argv[0]));
|
||||
rb_sys_fail(errmsg);
|
||||
}
|
||||
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
|
||||
return PIDT2NUM(pid);
|
||||
#else
|
||||
|
@ -4406,7 +4473,7 @@ proc_daemon(int argc, VALUE *argv)
|
|||
if (n < 0) rb_sys_fail("daemon");
|
||||
return INT2FIX(n);
|
||||
#elif defined(HAVE_FORK)
|
||||
switch (rb_fork(0, 0, 0, Qnil)) {
|
||||
switch (rb_fork(0, 0, 0, Qnil, NULL, 0)) {
|
||||
case -1:
|
||||
return (-1);
|
||||
case 0:
|
||||
|
|
Загрузка…
Ссылка в новой задаче