ruby-changes:48647
From: nobu <ko1@a...>
Date: Tue, 14 Nov 2017 13:42:44 +0900 (JST)
Subject: [ruby-changes:48647] nobu:r60762 (trunk): process.c: removed preserving_errno
nobu 2017-11-14 13:42:38 +0900 (Tue, 14 Nov 2017) New Revision: 60762 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60762 Log: process.c: removed preserving_errno * process.c (try_with_sh, handle_fork_error): added argument for errno. * process.c (proc_exec_cmd, proc_exec_sh, exec_async_signal_safe): now return errno instead of -1. * process.c (rb_fork_ruby): merged retry_fork_ruby() and unified clean-up after fork regardless failure. Modified files: trunk/process.c Index: process.c =================================================================== --- process.c (revision 60761) +++ process.c (revision 60762) @@ -143,11 +143,9 @@ int setregid(rb_gid_t rgid, rb_gid_t egi https://github.com/ruby/ruby/blob/trunk/process.c#L143 #endif #endif -#define preserving_errno(stmts) \ - do {int saved_errno = errno; stmts; errno = saved_errno;} while (0) - static void check_uid_switch(void); static void check_gid_switch(void); +static int exec_async_signal_safe(const struct rb_execarg *, char *, size_t); #if 1 #define p_uid_from_name p_uid_from_name @@ -1214,7 +1212,7 @@ security(const char *str) https://github.com/ruby/ruby/blob/trunk/process.c#L1212 #if defined(HAVE_WORKING_FORK) /* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/ -#define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0) +#define try_with_sh(err, prog, argv, envp) ((err == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0) static void exec_with_sh(const char *prog, char **argv, char **envp) { @@ -1237,26 +1235,28 @@ proc_exec_cmd(const char *prog, VALUE ar https://github.com/ruby/ruby/blob/trunk/process.c#L1235 char **argv; #ifndef _WIN32 char **envp; + int err; #endif argv = ARGVSTR2ARGV(argv_str); if (!prog) { - errno = ENOENT; - return -1; + return ENOENT; } #ifdef _WIN32 rb_w32_uaspawn(P_OVERLAY, prog, argv); + return errno; #else envp = envp_str ? (char **)RSTRING_PTR(envp_str) : NULL; if (envp_str) execve(prog, argv, envp); /* async-signal-safe */ else execv(prog, argv); /* async-signal-safe (since SUSv4) */ - preserving_errno(try_with_sh(prog, argv, envp)); /* try_with_sh() is async-signal-safe. */ + err = errno; + try_with_sh(err, prog, argv, envp); /* try_with_sh() is async-signal-safe. */ + return err; #endif - return -1; } /* This function should be async-signal-safe. Actually it is. */ @@ -1270,15 +1270,12 @@ proc_exec_sh(const char *str, VALUE envp https://github.com/ruby/ruby/blob/trunk/process.c#L1270 s++; if (!*s) { - errno = ENOENT; - return -1; + return ENOENT; } #ifdef _WIN32 rb_w32_uspawn(P_OVERLAY, (char *)str, 0); - return -1; -#else -#if defined(__CYGWIN32__) +#elif defined(__CYGWIN32__) { char fbuf[MAXPATHLEN]; char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf)); @@ -1295,9 +1292,8 @@ proc_exec_sh(const char *str, VALUE envp https://github.com/ruby/ruby/blob/trunk/process.c#L1292 execle("/bin/sh", "sh", "-c", str, (char *)NULL, (char **)RSTRING_PTR(envp_str)); /* async-signal-safe */ else execl("/bin/sh", "sh", "-c", str, (char *)NULL); /* async-signal-safe (since SUSv4) */ -#endif - return -1; #endif /* _WIN32 */ + return errno; } int @@ -1306,8 +1302,9 @@ rb_proc_exec(const char *str) https://github.com/ruby/ruby/blob/trunk/process.c#L1302 int ret; before_exec(); ret = proc_exec_sh(str, Qfalse); - preserving_errno(after_exec()); - return ret; + after_exec(); + errno = ret; + return -1; } static void @@ -2589,9 +2586,7 @@ rb_f_exec(int argc, const VALUE *argv) https://github.com/ruby/ruby/blob/trunk/process.c#L2586 rb_execarg_parent_start(execarg_obj); fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name; - rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg)); - - err = errno; + err = exec_async_signal_safe(eargp, errmsg, sizeof(errmsg)); after_exec(); /* restart timer thread */ rb_exec_fail(eargp, err, errmsg); @@ -3131,31 +3126,38 @@ rb_execarg_run_options(const struct rb_e https://github.com/ruby/ruby/blob/trunk/process.c#L3126 int rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen) { + errno = exec_async_signal_safe(eargp, errmsg, errmsg_buflen); + return -1; +} + +static int +exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen) +{ #if !defined(HAVE_WORKING_FORK) struct rb_execarg sarg, *const sargp = &sarg; #else struct rb_execarg *const sargp = NULL; #endif + int err; if (rb_execarg_run_options(eargp, sargp, errmsg, errmsg_buflen) < 0) { /* hopefully async-signal-safe */ - goto failure; + return errno; } if (eargp->use_shell) { - proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */ + err = proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */ } else { char *abspath = NULL; if (!NIL_P(eargp->invoke.cmd.command_abspath)) abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath); - proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */ + err = proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */ } #if !defined(HAVE_WORKING_FORK) - preserving_errno(rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen)); + rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen); #endif -failure: - return -1; + return err; } #ifdef HAVE_WORKING_FORK @@ -3226,11 +3228,11 @@ pipe_nocrash(int filedes[2], VALUE fds) https://github.com/ruby/ruby/blob/trunk/process.c#L3228 #endif static int -handle_fork_error(int *status, int *ep, volatile int *try_gc_p) +handle_fork_error(int err, int *status, int *ep, volatile int *try_gc_p) { int state = 0; - switch (errno) { + switch (err) { case ENOMEM: if ((*try_gc_p)-- > 0 && !rb_during_gc()) { rb_gc(); @@ -3253,7 +3255,9 @@ handle_fork_error(int *status, int *ep, https://github.com/ruby/ruby/blob/trunk/process.c#L3255 break; } if (ep) { - preserving_errno((close(ep[0]), close(ep[1]))); + close(ep[0]); + close(ep[1]); + errno = err; } if (state && !status) rb_jump_tag(state); return -1; @@ -3548,6 +3552,7 @@ retry_fork_async_signal_safe(int *status https://github.com/ruby/ruby/blob/trunk/process.c#L3552 rb_pid_t pid; volatile int try_gc = 1; struct child_handler_disabler_state old; + int err; while (1) { prefork(); @@ -3575,11 +3580,12 @@ retry_fork_async_signal_safe(int *status https://github.com/ruby/ruby/blob/trunk/process.c#L3580 _exit(127); #endif } - preserving_errno(disable_child_handler_fork_parent(&old)); + err = errno; + disable_child_handler_fork_parent(&old); if (0 < pid) /* fork succeed, parent process */ return pid; /* fork failed */ - if (handle_fork_error(status, ep, &try_gc)) + if (handle_fork_error(err, status, ep, &try_gc)) return -1; } } @@ -3614,45 +3620,29 @@ rb_fork_async_signal_safe(int *status, i https://github.com/ruby/ruby/blob/trunk/process.c#L3620 return pid; } -static rb_pid_t -retry_fork_ruby(int *status, struct child_handler_disabler_state *old) -{ - rb_pid_t pid; - int try_gc = 1; - - while (1) { - prefork(); - before_fork_ruby(); - disable_child_handler_before_fork(old); - pid = fork(); - if (pid == 0) /* fork succeed, child process */ - return pid; - preserving_errno(after_fork_ruby()); - preserving_errno(disable_child_handler_fork_parent(old)); - if (0 < pid) /* fork succeed, parent process */ - return pid; - /* fork failed */ - if (handle_fork_error(status, NULL, &try_gc)) - return -1; - } -} - rb_pid_t rb_fork_ruby(int *status) { rb_pid_t pid; + int try_gc = 1, err; struct child_handler_disabler_state old; if (status) *status = 0; - pid = retry_fork_ruby(status, &old); - if (pid < 0) - return pid; - if (!pid) { - after_fork_ruby(); - disable_child_handler_fork_parent(&old); /* yes, bad name */ + while (1) { + prefork(); + before_fork_ruby(); + disable_child_handler_before_fork(&old); + pid = fork(); + err = errno; + after_fork_ruby(); + disable_child_handler_fork_parent(&old); /* yes, bad name */ + if (pid >= 0) /* fork succeed */ + return pid; + /* fork failed */ + if (handle_fork_error(err, status, NULL, &try_gc)) + return -1; } - return pid; } #endif -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/