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

ruby-changes:4902

From: ko1@a...
Date: Mon, 12 May 2008 23:15:59 +0900 (JST)
Subject: [ruby-changes:4902] usa - Ruby:r16395 (trunk): * process.c, include/ruby/intern.h (rb_run_exec_options): externed.

usa	2008-05-12 23:15:32 +0900 (Mon, 12 May 2008)

  New Revision: 16395

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/intern.h
    trunk/io.c
    trunk/process.c
    trunk/test/ruby/test_process.rb
    trunk/win32/win32.c

  Log:
    * process.c, include/ruby/intern.h (rb_run_exec_options): externed.
    
    * process.c (save_redirect_fd, save_env_i, save_env, run_exec_dup2,
      run_exec_open, run_exec_pgroup, run_exec_rlimit, rb_run_exec_options):
      save parent's process environments.
      !!!remark!!! these are not thread-safe.
    
    * process.c (rb_spawn_internal): remove calling run_exec_options()
      because cannot restore after spawn. we'll fix this later.
    
    * io.c (pipe_open): ditto.
    
    * test/ruby/test_process.rb (test_execopts_env): upcase environment
      variable name for case insensitive platforms.
    
    * win32/win32.c (init_env): set USER environment variable only when
      USERNAME is available.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/win32/win32.c?r1=16395&r2=16394&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_process.rb?r1=16395&r2=16394&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16395&r2=16394&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/io.c?r1=16395&r2=16394&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/process.c?r1=16395&r2=16394&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/intern.h?r1=16395&r2=16394&diff_format=u

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 16394)
+++ include/ruby/intern.h	(revision 16395)
@@ -457,6 +457,7 @@
 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);
 VALUE rb_f_exec(int,VALUE*);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 16394)
+++ ChangeLog	(revision 16395)
@@ -1,3 +1,23 @@
+Mon May 12 23:05:24 2008  NAKAMURA Usaku  <usa@r...>
+
+	* process.c, include/ruby/intern.h (rb_run_exec_options): externed.
+
+	* process.c (save_redirect_fd, save_env_i, save_env, run_exec_dup2,
+	  run_exec_open, run_exec_pgroup, run_exec_rlimit, rb_run_exec_options):
+	  save parent's process environments.
+	  !!!remark!!! these are not thread-safe.
+
+	* process.c (rb_spawn_internal): remove calling run_exec_options()
+	  because cannot restore after spawn. we'll fix this later.
+
+	* io.c (pipe_open): ditto.
+
+	* test/ruby/test_process.rb (test_execopts_env): upcase environment
+	  variable name for case insensitive platforms.
+
+	* win32/win32.c (init_env): set USER environment variable only when
+	  USERNAME is available.
+
 Mon May 12 22:23:01 2008  Tanaka Akira  <akr@f...>
 
 	* lib/date.rb (once): use Object#object_id instead of Symbol#to_i.
Index: io.c
===================================================================
--- io.c	(revision 16394)
+++ io.c	(revision 16395)
@@ -3692,6 +3692,7 @@
     int openmode = rb_io_mode_modenum(mode);
     const char *exename = NULL;
     volatile VALUE cmdbuf;
+    struct rb_exec_arg sarg;
 #endif
     FILE *fp = 0;
     int fd = -1;
@@ -3822,6 +3823,10 @@
 	cmd = rb_w32_join_argv(RSTRING_PTR(cmdbuf), args);
 	rb_str_resize(argbuf, 0);
     }
+    if (eargp) {
+	rb_exec_arg_fixup(eargp);
+	rb_run_exec_options(eargp, &sarg);
+    }
     while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd, &write_fd)) == -1) {
 	/* exec failed */
 	switch (errno) {
@@ -3832,16 +3837,26 @@
 	    rb_thread_sleep(1);
 	    break;
 	  default:
+	    if (eargp)
+		rb_run_exec_options(&sarg, NULL);
 	    rb_sys_fail(cmd);
 	    break;
 	}
     }
+    if (eargp)
+	rb_run_exec_options(&sarg, NULL);
 #else
     if (argc) {
 	prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
 	cmd = StringValueCStr(prog);
     }
+    if (eargp) {
+	rb_exec_arg_fixup(eargp);
+	rb_run_exec_options(eargp, &sarg);
+    }
     fp = popen(cmd, mode);
+    if (eargp)
+	rb_run_exec_options(&sarg, NULL);
     if (!fp) rb_sys_fail(RSTRING_PTR(prog));
     fd = fileno(fp);
 #endif
Index: win32/win32.c
===================================================================
--- win32/win32.c	(revision 16394)
+++ win32/win32.c	(revision 16395)
@@ -376,11 +376,10 @@
     }
 
     if (!GetEnvironmentVariable("USER", env, sizeof env)) {
-	if (GetEnvironmentVariable("USERNAME", env, sizeof env) ||
-	    GetUserName(env, (len = sizeof env, &len))) {
+	if (GetEnvironmentVariable("USERNAME", env, sizeof env)) {
 	    SetEnvironmentVariable("USER", env);
 	}
-	else {
+	else if (!GetUserName(env, (len = sizeof env, &len))) {
 	    NTLoginName = "<Unknown>";
 	    return;
 	}
Index: process.c
===================================================================
--- process.c	(revision 16394)
+++ process.c	(revision 16395)
@@ -1783,13 +1783,61 @@
 #endif
 
 static int
+save_redirect_fd(int fd, VALUE save)
+{
+    if (!NIL_P(save)) {
+        VALUE newary;
+        int save_fd = redirect_dup(fd);
+        if (save_fd == -1) return -1;
+        newary = rb_ary_entry(save, EXEC_OPTION_DUP2);
+        if (NIL_P(newary)) {
+            newary = hide_obj(rb_ary_new());
+            rb_ary_store(save, EXEC_OPTION_DUP2, newary);
+        }
+        rb_ary_push(newary,
+                    hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
+
+        newary = rb_ary_entry(save, EXEC_OPTION_CLOSE);
+        if (NIL_P(newary)) {
+            newary = hide_obj(rb_ary_new());
+            rb_ary_store(save, EXEC_OPTION_CLOSE, newary);
+        }
+        rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
+    }
+
+    return 0;
+}
+
+static VALUE
+save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
+{
+    rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
+    return Qnil;
+}
+
+static void
+save_env(VALUE save)
+{
+    if (!NIL_P(save) && NIL_P(rb_ary_entry(save, EXEC_OPTION_ENV))) {
+        VALUE env = rb_const_get(rb_cObject, rb_intern("ENV"));
+        if (RTEST(env)) {
+            VALUE ary = hide_obj(rb_ary_new());
+            rb_block_call(env, rb_intern("each"), 0, 0, save_env_i,
+                          (VALUE)ary);
+            rb_ary_store(save, EXEC_OPTION_ENV, ary);
+        }
+        rb_ary_store(save, EXEC_OPTION_UNSETENV_OTHERS, Qtrue);
+    }
+}
+
+static int
 intcmp(const void *a, const void *b)
 {
     return *(int*)a - *(int*)b;
 }
 
 static int
-run_exec_dup2(VALUE ary)
+run_exec_dup2(VALUE ary, VALUE save)
 {
     int n, i;
     int ret;
@@ -1837,6 +1885,8 @@
     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)
+                return -1;
             ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
             if (ret == -1)
                 goto fail;
@@ -1919,7 +1969,7 @@
 }
 
 static int
-run_exec_open(VALUE ary)
+run_exec_open(VALUE ary, VALUE save)
 {
     int i, ret;
 
@@ -1940,6 +1990,8 @@
                 need_close = 0;
             }
             else {
+                if (save_redirect_fd(fd, save) < 0)
+                    return -1;
                 ret = redirect_dup2(fd2, fd);
                 if (ret == -1) return -1;
             }
@@ -1955,14 +2007,18 @@
 
 #ifdef HAVE_SETPGID
 static int
-run_exec_pgroup(VALUE obj)
+run_exec_pgroup(VALUE obj, VALUE save)
 {
     /*
      * If FD_CLOEXEC is available, rb_fork waits the child's execve.
      * So setpgid is done in the child when rb_fork is returned in the parent.
      * No race condition, even without setpgid from the parent.
      * (Is there an environment which has setpgid but FD_CLOEXEC?)
-     */ 
+     */
+    if (!NIL_P(save)) {
+        /* maybe meaningless with no fork environment... */
+        rb_ary_store(save, EXEC_OPTION_PGROUP, PIDT2NUM(getpgrp()));
+    }
     pid_t pgroup = NUM2PIDT(obj);
     if (pgroup == 0) {
         pgroup = getpid();
@@ -1973,13 +2029,26 @@
 
 #ifdef RLIM2NUM
 static int
-run_exec_rlimit(VALUE ary)
+run_exec_rlimit(VALUE ary, VALUE save)
 {
     int i;
     for (i = 0; i < RARRAY_LEN(ary); i++) {
         VALUE elt = RARRAY_PTR(ary)[i];
         int rtype = NUM2INT(RARRAY_PTR(elt)[0]);
         struct rlimit rlim;
+        if (!NIL_P(save)) {
+            if (getrlimit(rtype, &rlim) == -1)
+                return -1;
+            VALUE tmp = hide_obj(rb_ary_new3(3, RARRAY_PTR(elt)[0],
+                                             RLIM2NUM(rlim.rlim_cur),
+                                             RLIM2NUM(rlim.rlim_max)));
+            VALUE newary = rb_ary_entry(save, EXEC_OPTION_RLIMIT);
+            if (NIL_P(newary)) {
+                newary = hide_obj(rb_ary_new());
+                rb_ary_store(save, EXEC_OPTION_RLIMIT, newary);
+            }
+            rb_ary_push(newary, tmp);
+        }
         rlim.rlim_cur = NUM2RLIM(RARRAY_PTR(elt)[1]);
         rlim.rlim_max = NUM2RLIM(RARRAY_PTR(elt)[2]);
         if (setrlimit(rtype, &rlim) == -1)
@@ -1989,19 +2058,28 @@
 }
 #endif
 
-static int
-run_exec_options(const struct rb_exec_arg *e)
+int
+rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
 {
     VALUE options = e->options;
+    VALUE soptions = Qnil;
     VALUE obj;
 
     if (!RTEST(options))
         return 0;
 
+    if (s) {
+        s->argc = 0;
+        s->argv = NULL;
+        s->prog = NULL;
+        s->options = soptions = hide_obj(rb_ary_new());
+        s->redirect_fds = Qnil;
+    }
+
 #ifdef HAVE_SETPGID
     obj = rb_ary_entry(options, EXEC_OPTION_PGROUP);
     if (RTEST(obj)) {
-        if (run_exec_pgroup(obj) == -1)
+        if (run_exec_pgroup(obj, soptions) == -1)
             return -1;
     }
 #endif
@@ -2009,19 +2087,21 @@
 #ifdef RLIM2NUM
     obj = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
     if (!NIL_P(obj)) {
-        if (run_exec_rlimit(obj) == -1)
+        if (run_exec_rlimit(obj, soptions) == -1)
             return -1;
     }
 #endif
 
     obj = rb_ary_entry(options, EXEC_OPTION_UNSETENV_OTHERS);
     if (RTEST(obj)) {
+        save_env(soptions);
         rb_env_clear();
     }
 
     obj = rb_ary_entry(options, EXEC_OPTION_ENV);
     if (!NIL_P(obj)) {
         int i;
+        save_env(soptions);
         for (i = 0; i < RARRAY_LEN(obj); i++) {
             VALUE pair = RARRAY_PTR(obj)[i];
             VALUE key = RARRAY_PTR(pair)[0];
@@ -2035,6 +2115,11 @@
 
     obj = rb_ary_entry(options, EXEC_OPTION_CHDIR);
     if (!NIL_P(obj)) {
+        if (!NIL_P(soptions)) {
+            char *cwd = my_getcwd();
+            rb_ary_store(soptions, EXEC_OPTION_CHDIR,
+                         hide_obj(rb_str_new2(cwd)));
+        }
         if (chdir(RSTRING_PTR(obj)) == -1)
             return -1;
     }
@@ -2042,19 +2127,25 @@
     obj = rb_ary_entry(options, EXEC_OPTION_UMASK);
     if (!NIL_P(obj)) {
         mode_t mask = NUM2LONG(obj);
-        umask(mask); /* never fail */
+        mode_t oldmask = umask(mask); /* never fail */
+        if (!NIL_P(soptions))
+            rb_ary_store(soptions, EXEC_OPTION_UMASK, LONG2NUM(oldmask));
     }
 
     obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
     if (!NIL_P(obj)) {
-        if (run_exec_dup2(obj) == -1)
+        if (run_exec_dup2(obj, soptions) == -1)
             return -1;
     }
 
     obj = rb_ary_entry(options, EXEC_OPTION_CLOSE);
     if (!NIL_P(obj)) {
-        if (run_exec_close(obj) == -1)
-            return -1;
+        if (!NIL_P(soptions))
+            rb_warn("cannot close fd before spawn");
+        else {
+            if (run_exec_close(obj) == -1)
+                return -1;
+        }
     }
 
 #ifdef HAVE_FORK
@@ -2066,7 +2157,7 @@
 
     obj = rb_ary_entry(options, EXEC_OPTION_OPEN);
     if (!NIL_P(obj)) {
-        if (run_exec_open(obj) == -1)
+        if (run_exec_open(obj, soptions) == -1)
             return -1;
     }
 
@@ -2080,7 +2171,7 @@
     VALUE *argv = e->argv;
     const char *prog = e->prog;
 
-    if (run_exec_options(e) < 0) {
+    if (rb_run_exec_options(e, NULL) < 0) {
         return -1;
     }
 
@@ -2554,6 +2645,9 @@
     rb_pid_t status;
     VALUE prog;
     struct rb_exec_arg earg;
+#if !defined HAVE_FORK
+    struct rb_exec_arg sarg;
+#endif
 
     prog = rb_exec_arg_init(argc, argv, Qtrue, &earg);
     if (NIL_P(rb_ary_entry(earg.options, EXEC_OPTION_CLOSE_OTHERS))) {
@@ -2566,11 +2660,9 @@
     status = rb_fork(&status, rb_exec_atfork, &earg, earg.redirect_fds);
     if (prog && earg.argc) earg.argv[0] = prog;
 #else
-    /* XXXXX: need to call this func, but cannot restore after spawn...
-    if (run_exec_options(&earg) < 0) {
+    if (rb_run_exec_options(&earg, &sarg) < 0) {
         return -1;
     }
-    */
 
     argc = earg.argc;
     argv = earg.argv;
@@ -2591,6 +2683,8 @@
     rb_last_status_set((status & 0xff) << 8, 0);
 #  endif
 # endif
+
+    rb_run_exec_options(&sarg, NULL);
 #endif
     return status;
 }
Index: test/ruby/test_process.rb
===================================================================
--- test/ruby/test_process.rb	(revision 16394)
+++ test/ruby/test_process.rb	(revision 16395)
@@ -195,8 +195,8 @@
     }
 
     h = {}
-    ENV.each {|k,v| h[k] = nil unless k == "PATH" }
-    IO.popen([h, RUBY, '-e', 'puts ENV.keys']) {|io|
+    ENV.each {|k,v| h[k] = nil unless k.upcase == "PATH" }
+    IO.popen([h, RUBY, '-e', 'puts ENV.keys.map{|e|e.upcase}']) {|io|
       assert_equal("PATH\n", io.read)
     }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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