[PATCH 1 of 3] serve: add and use portable spawnvp replacement
Patrick Mezard
pmezard at gmail.com
Wed Jan 6 20:59:37 UTC 2010
# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1239391225 -7200
# Node ID 92ac4240b6e0e3c1b959eb481f0e058e61ee705a
# Parent 3ab391dd5ec5ab1f4af06169bde7a9c850a7f4ce
serve: add and use portable spawnvp replacement
There is no standard python command to really detach a process
under Windows. Instead we use the low level API wrapped by
subprocess module with all necessary options to avoid any kind
of context inheritance.
Fix 1/3 for issue421
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -580,8 +580,7 @@
elif runargs[i].startswith('--cwd'):
del runargs[i:i+2]
break
- pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
- runargs[0], runargs)
+ pid = util.spawndetached(runargs)
os.close(wfd)
os.read(rfd, 1)
if parentfn:
diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -245,3 +245,8 @@
return grp.getgrgid(gid)[0]
except KeyError:
return str(gid)
+
+def spawndetached(args):
+ return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
+ args[0], args)
+
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -7,7 +7,7 @@
from i18n import _
import osutil, error
-import errno, msvcrt, os, re, sys, random
+import errno, msvcrt, os, re, sys, random, subprocess
nulldev = 'NUL:'
umask = 002
@@ -59,6 +59,16 @@
self.close()
raise IOError(errno.EPIPE, 'Broken pipe')
+ # Standard streams descriptors are set to -1 in child processes
+ # not inheriting their parent handles. And raise IOError instead of
+ # ignoring read/write calls.
+ if not hasattr(sys.stdin, 'fileno') or sys.stdin.fileno() == -1:
+ sys.stdin = open(nulldev, 'r')
+ if not hasattr(sys.stderr, 'fileno') or sys.stderr.fileno() == -1:
+ sys.stderr = open(nulldev, 'w')
+ if not hasattr(sys.stdout, 'fileno') or sys.stdout.fileno() == -1:
+ sys.stdout = open(nulldev, 'w')
+
sys.stdout = winstdout(sys.stdout)
def _is_win_9x():
@@ -321,6 +331,35 @@
pass
os.rename(src, dst)
+def spawndetached(args):
+ # No standard library function really spawns a fully detached
+ # process under win32 because they allocate pipes or other objects
+ # to handle standard streams communications. Passing these objects
+ # to the child process requires handle inheritance to be enabled
+ # which makes really detached processes impossible.
+
+ class STARTUPINFO:
+ dwFlags = 0
+ hStdInput = None
+ hStdOutput = None
+ hStdError = None
+ wShowWindow = 0
+
+ path = args[0]
+ args = subprocess.list2cmdline(args)
+ hp, ht, pid, tid = subprocess.CreateProcess(
+ path, args,
+ # no special security
+ None, None,
+ # Do not inherit handles
+ 0,
+ # DETACHED_PROCESS
+ 0x00000008,
+ os.environ,
+ os.getcwd(),
+ STARTUPINFO())
+ return pid
+
try:
# override functions with win32 versions if possible
from win32 import *
More information about the Mercurial-devel
mailing list