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

ruby-changes:23281

From: naruse <ko1@a...>
Date: Sun, 15 Apr 2012 06:48:04 +0900 (JST)
Subject: [ruby-changes:23281] naruse:r35332 (ruby_1_9_3): merge revision(s) 35249,35250: [Backport #6296]

naruse	2012-04-15 06:47:27 +0900 (Sun, 15 Apr 2012)

  New Revision: 35332

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35332

  Log:
    merge revision(s) 35249,35250: [Backport #6296]
    
    * include/ruby/win32.h (rb_w32_aspawn_flags): add the declaration of
      new function.
    
    * process.c (enum): add EXEC_OPTION_PGROUP and move the position
      above for the usage in proc_spawn_n().
    
    * process.c (proc_spawn_n): add an argument to pass new option
      `new_pgroup`. The option specifies CREATE_NEW_PROCESS_GROUP flag to
      CreateProcessW(). This flag is necessary for the usage of
      Process.kill on the subprocess on Windows.
    
    * process.c (rb_exec_arg_addopt): ditto.
    
    * process.c (rb_spawn_process): ditto.
    
    * process.c (documentation for rb_f_spawn): add documentation for new
      option `new_pgroup` of spawn.
    
    * test/ruby/test_process.rb (TestProcess#test_execopts_new_pgroup):
      add tests for option `new_pgroup`.
    
    * test/ruby/test_thread.rb
      (TestThreadGroup#test_thread_timer_and_interrupt):
      add option `new_pgroup: true` to spawn on Windows. It's needed for
      Process.kill on a subprocess.
    
    * win32/win32.c (CreateChild): add an argument to pass
      dwCreationFlags of CreateProcessW().
    
    * win32/win32.c (rb_w32_spawn): ditto.
    
    * win32/win32.c (rb_w32_aspawn_flags): add new function to pass
      dwCreationFlags.
    
    * win32/win32.c (rb_w32_aspawn): refactor to move the content to
      rb_w32_aspawn_flags().
      [ruby-core:43245][Bug #6131]
    
    * test/ruby/test_thread.rb
      (TestThreadGroup#test_thread_timer_and_interrupt): skip on Windows.
      Process.kill cannot kill a subprocess if CREATE_NEW_PROCESS_GROUP
      flag is not specified in a call to CreateProcessW().
    
    * win32/win32.c (CreateChild): revert the usage of
      CREATE_NEW_PROCESS_GROUP flag for compatibility.
      [ruby-core:43245][Bug #6131]

  Modified files:
    branches/ruby_1_9_3/ChangeLog
    branches/ruby_1_9_3/include/ruby/win32.h
    branches/ruby_1_9_3/process.c
    branches/ruby_1_9_3/test/ruby/test_process.rb
    branches/ruby_1_9_3/test/ruby/test_thread.rb
    branches/ruby_1_9_3/version.h
    branches/ruby_1_9_3/win32/win32.c

Index: ruby_1_9_3/include/ruby/win32.h
===================================================================
--- ruby_1_9_3/include/ruby/win32.h	(revision 35331)
+++ ruby_1_9_3/include/ruby/win32.h	(revision 35332)
@@ -284,6 +284,7 @@
 extern rb_pid_t waitpid (rb_pid_t, int *, int);
 extern rb_pid_t rb_w32_spawn(int, const char *, const char*);
 extern rb_pid_t rb_w32_aspawn(int, const char *, char *const *);
+extern rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD);
 extern int kill(int, int);
 extern int fcntl(int, int, ...);
 extern rb_pid_t rb_w32_getpid(void);
Index: ruby_1_9_3/ChangeLog
===================================================================
--- ruby_1_9_3/ChangeLog	(revision 35331)
+++ ruby_1_9_3/ChangeLog	(revision 35332)
@@ -1,3 +1,54 @@
+Sun Apr 15 06:40:28 2012  Hiroshi Shirosaki  <h.shirosaki@g...>
+
+	* include/ruby/win32.h (rb_w32_aspawn_flags): add the declaration of
+	  new function.
+
+	* process.c (enum): add EXEC_OPTION_PGROUP and move the position
+	  above for the usage in proc_spawn_n().
+
+	* process.c (proc_spawn_n): add an argument to pass new option
+	  `new_pgroup`. The option specifies CREATE_NEW_PROCESS_GROUP flag to
+	  CreateProcessW(). This flag is necessary for the usage of
+	  Process.kill on the subprocess on Windows.
+
+	* process.c (rb_exec_arg_addopt): ditto.
+
+	* process.c (rb_spawn_process): ditto.
+
+	* process.c (documentation for rb_f_spawn): add documentation for new
+	  option `new_pgroup` of spawn.
+
+	* test/ruby/test_process.rb (TestProcess#test_execopts_new_pgroup):
+	  add tests for option `new_pgroup`.
+
+	* test/ruby/test_thread.rb
+	  (TestThreadGroup#test_thread_timer_and_interrupt):
+	  add option `new_pgroup: true` to spawn on Windows. It's needed for
+	  Process.kill on a subprocess.
+
+	* win32/win32.c (CreateChild): add an argument to pass
+	  dwCreationFlags of CreateProcessW().
+
+	* win32/win32.c (rb_w32_spawn): ditto.
+
+	* win32/win32.c (rb_w32_aspawn_flags): add new function to pass
+	  dwCreationFlags.
+
+	* win32/win32.c (rb_w32_aspawn): refactor to move the content to
+	  rb_w32_aspawn_flags().
+	  [ruby-core:43245][Bug #6131]
+
+Sun Apr 15 06:40:28 2012  Hiroshi Shirosaki  <h.shirosaki@g...>
+
+	* test/ruby/test_thread.rb
+	  (TestThreadGroup#test_thread_timer_and_interrupt): skip on Windows.
+	  Process.kill cannot kill a subprocess if CREATE_NEW_PROCESS_GROUP
+	  flag is not specified in a call to CreateProcessW().
+
+	* win32/win32.c (CreateChild): revert the usage of
+	  CREATE_NEW_PROCESS_GROUP flag for compatibility.
+	  [ruby-core:43245][Bug #6131]
+
 Sun Apr 15 04:35:48 2012  Hiroshi Shirosaki  <h.shirosaki@g...>
 
 	* io.c (rb_io_eof): use eof() instead of io_fillbuf(). It's because
Index: ruby_1_9_3/win32/win32.c
===================================================================
--- ruby_1_9_3/win32/win32.c	(revision 35331)
+++ ruby_1_9_3/win32/win32.c	(revision 35332)
@@ -63,7 +63,7 @@
 
 #define TO_SOCKET(x)	_get_osfhandle(x)
 
-static struct ChildRecord *CreateChild(const WCHAR *, const WCHAR *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
+static struct ChildRecord *CreateChild(const WCHAR *, const WCHAR *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE, DWORD);
 static int has_redirection(const char *);
 int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
 static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags);
@@ -1008,10 +1008,9 @@
 
 static struct ChildRecord *
 CreateChild(const WCHAR *cmd, const WCHAR *prog, SECURITY_ATTRIBUTES *psa,
-	    HANDLE hInput, HANDLE hOutput, HANDLE hError)
+	    HANDLE hInput, HANDLE hOutput, HANDLE hError, DWORD dwCreationFlags)
 {
     BOOL fRet;
-    DWORD  dwCreationFlags;
     STARTUPINFOW aStartupInfo;
     PROCESS_INFORMATION aProcessInformation;
     SECURITY_ATTRIBUTES sa;
@@ -1058,7 +1057,7 @@
 	aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
     }
 
-    dwCreationFlags = (CREATE_NEW_PROCESS_GROUP | NORMAL_PRIORITY_CLASS);
+    dwCreationFlags |= NORMAL_PRIORITY_CLASS;
 
     if (lstrlenW(cmd) > 32767) {
 	child->pid = 0;		/* release the slot */
@@ -1209,14 +1208,14 @@
     wshell = shell ? acp_to_wstr(shell, NULL) : NULL;
     if (v2) ALLOCV_END(v2);
 
-    ret = child_result(CreateChild(wcmd, wshell, NULL, NULL, NULL, NULL), mode);
+    ret = child_result(CreateChild(wcmd, wshell, NULL, NULL, NULL, NULL, 0), mode);
     free(wshell);
     free(wcmd);
     return ret;
 }
 
 rb_pid_t
-rb_w32_aspawn(int mode, const char *prog, char *const *argv)
+rb_w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags)
 {
     int c_switch = 0;
     size_t len;
@@ -1275,12 +1274,19 @@
     if (v) ALLOCV_END(v);
     wprog = prog ? acp_to_wstr(prog, NULL) : NULL;
 
-    ret = child_result(CreateChild(wcmd, wprog, NULL, NULL, NULL, NULL), mode);
+    ret = child_result(CreateChild(wcmd, wprog, NULL, NULL, NULL, NULL, flags), mode);
     free(wprog);
     free(wcmd);
     return ret;
 }
 
+rb_pid_t
+rb_w32_aspawn(int mode, const char *prog, char *const *argv)
+{
+    return rb_w32_aspawn_flags(mode, prog, argv, 0);
+}
+
+/* License: Artistic or GPL */
 typedef struct _NtCmdLineElement {
     struct _NtCmdLineElement *next;
     char *str;
Index: ruby_1_9_3/process.c
===================================================================
--- ruby_1_9_3/process.c	(revision 35331)
+++ ruby_1_9_3/process.c	(revision 35332)
@@ -1216,6 +1216,21 @@
 #endif	/* _WIN32 */
 }
 
+enum {
+    EXEC_OPTION_PGROUP,
+    EXEC_OPTION_RLIMIT,
+    EXEC_OPTION_UNSETENV_OTHERS,
+    EXEC_OPTION_ENV,
+    EXEC_OPTION_CHDIR,
+    EXEC_OPTION_UMASK,
+    EXEC_OPTION_DUP2,
+    EXEC_OPTION_CLOSE,
+    EXEC_OPTION_OPEN,
+    EXEC_OPTION_DUP2_CHILD,
+    EXEC_OPTION_CLOSE_OTHERS,
+    EXEC_OPTION_NEW_PGROUP
+};
+
 #if defined(_WIN32)
 #define HAVE_SPAWNV 1
 #endif
@@ -1261,7 +1276,7 @@
 #endif
 
 static rb_pid_t
-proc_spawn_n(int argc, VALUE *argv, VALUE prog)
+proc_spawn_n(int argc, VALUE *argv, VALUE prog, VALUE options)
 {
     char **args;
     int i;
@@ -1273,8 +1288,17 @@
 	args[i] = RSTRING_PTR(argv[i]);
     }
     args[i] = (char*) 0;
-    if (args[0])
+    if (args[0]) {
+#if defined(_WIN32)
+	DWORD flags = 0;
+	if (RTEST(rb_ary_entry(options, EXEC_OPTION_NEW_PGROUP))) {
+	    flags = CREATE_NEW_PROCESS_GROUP;
+	}
+	pid = rb_w32_aspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, args, flags);
+#else
 	pid = proc_spawn_v(args, prog ? RSTRING_PTR(prog) : 0);
+#endif
+    }
     ALLOCV_END(v);
     return pid;
 }
@@ -1322,20 +1346,6 @@
     return obj;
 }
 
-enum {
-    EXEC_OPTION_PGROUP,
-    EXEC_OPTION_RLIMIT,
-    EXEC_OPTION_UNSETENV_OTHERS,
-    EXEC_OPTION_ENV,
-    EXEC_OPTION_CHDIR,
-    EXEC_OPTION_UMASK,
-    EXEC_OPTION_DUP2,
-    EXEC_OPTION_CLOSE,
-    EXEC_OPTION_OPEN,
-    EXEC_OPTION_DUP2_CHILD,
-    EXEC_OPTION_CLOSE_OTHERS
-};
-
 static VALUE
 check_exec_redirect_fd(VALUE v, int iskey)
 {
@@ -1519,6 +1529,16 @@
         }
         else
 #endif
+#ifdef _WIN32
+        if (id == rb_intern("new_pgroup")) {
+            if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_NEW_PGROUP))) {
+                rb_raise(rb_eArgError, "new_pgroup option specified twice");
+            }
+            val = RTEST(val) ? Qtrue : Qfalse;
+            rb_ary_store(options, EXEC_OPTION_NEW_PGROUP, val);
+        }
+        else
+#endif
 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
         if (strncmp("rlimit_", rb_id2name(id), 7) == 0 &&
             (rtype = rlimit_type_by_lname(rb_id2name(id)+7)) != -1) {
@@ -3050,7 +3070,7 @@
 	pid = proc_spawn(RSTRING_PTR(prog));
     }
     else {
-	pid = proc_spawn_n(argc, argv, prog);
+	pid = proc_spawn_n(argc, argv, prog, earg->options);
     }
 #  if defined(_WIN32)
     if (pid == -1)
@@ -3185,6 +3205,9 @@
  *        :pgroup => true or 0 : make a new process group
  *        :pgroup => pgid      : join to specified process group
  *        :pgroup => nil       : don't change the process group (default)
+ *      create new process group: Windows only
+ *        :new_pgroup => true  : the new process is the root process of a new process group
+ *        :new_pgroup => false : don't create a new process group (default)
  *      resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
  *        :rlimit_resourcename => limit
  *        :rlimit_resourcename => [cur_limit, max_limit]
@@ -3224,6 +3247,7 @@
  *  If a hash is given as +options+,
  *  it specifies
  *  process group,
+ *  create new process group,
  *  resource limit,
  *  current directory,
  *  umask and
@@ -3245,6 +3269,17 @@
  *    pid = spawn(command, :pgroup=>true) # process leader
  *    pid = spawn(command, :pgroup=>10) # belongs to the process group 10
  *
+ *  The <code>:new_pgroup</code> key in +options+ specifies to pass
+ *  +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
+ *  Windows API. This option is only for Windows.
+ *  true means the new process is the root process of the new process group.
+ *  The new process has CTRL+C disabled. This flag is necessary for
+ *  <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
+ *  :new_pgroup is false by default.
+ *
+ *    pid = spawn(command, :new_pgroup=>true)  # new process group
+ *    pid = spawn(command, :new_pgroup=>false) # same process group
+ *
  *  The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
  *  <em>foo</em> should be one of resource types such as <code>core</code>.
  *  The corresponding value should be an integer or an array which have one or
Index: ruby_1_9_3/version.h
===================================================================
--- ruby_1_9_3/version.h	(revision 35331)
+++ ruby_1_9_3/version.h	(revision 35332)
@@ -1,5 +1,5 @@
 #define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 181
+#define RUBY_PATCHLEVEL 182
 
 #define RUBY_RELEASE_DATE "2012-04-15"
 #define RUBY_RELEASE_YEAR 2012
Index: ruby_1_9_3/test/ruby/test_process.rb
===================================================================
--- ruby_1_9_3/test/ruby/test_process.rb	(revision 35331)
+++ ruby_1_9_3/test/ruby/test_process.rb	(revision 35332)
@@ -1327,4 +1327,13 @@
       end
     end
   end
+
+  def test_execopts_new_pgroup
+    return unless windows?
+
+    assert_nothing_raised { system(*TRUECOMMAND, :new_pgroup=>true) }
+    assert_nothing_raised { system(*TRUECOMMAND, :new_pgroup=>false) }
+    assert_nothing_raised { spawn(*TRUECOMMAND, :new_pgroup=>true) }
+    assert_nothing_raised { IO.popen([*TRUECOMMAND, :new_pgroup=>true]) {} }
+  end
 end
Index: ruby_1_9_3/test/ruby/test_thread.rb
===================================================================
--- ruby_1_9_3/test/ruby/test_thread.rb	(revision 35331)
+++ ruby_1_9_3/test/ruby/test_thread.rb	(revision 35332)
@@ -691,7 +691,9 @@
     t0 = Time.now.to_f
     pid = nil
     cmd = 'r,=IO.pipe; Thread.start {Thread.pass until Thread.main.stop?; puts; STDOUT.flush}; r.read'
-    s, err = EnvUtil.invoke_ruby(['-e', cmd], "", true, true) do |in_p, out_p, err_p, cpid|
+    opt = {}
+    opt[:new_pgroup] = true if /mswin|mingw/ =~ RUBY_PLATFORM
+    s, err = EnvUtil.invoke_ruby(['-e', cmd], "", true, true, opt) do |in_p, out_p, err_p, cpid|
       out_p.gets
       pid = cpid
       Process.kill(:SIGINT, pid)

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

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