[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]