[PATCH 1 of 4] win32: drop a py26 daemonizing hack

Matt Harbison mharbison72 at gmail.com
Mon Jun 5 03:38:48 UTC 2017


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1495407531 14400
#      Sun May 21 18:58:51 2017 -0400
# Node ID ecc27f3123ea173f2dc66e20abbedad5741ea5e1
# Parent  fc9296c15112af247e4985cdc45fbbf7d8eed175
win32: drop a py26 daemonizing hack

I'm not sure what the referenced hang specifically was, but the whole test suite
(with #serve) still runs on python 2.7.13.  Aside from no longer prepending
"cmd.exe /c", this backs out ca6aa8362f33.

I'm trying to track down a rare failure of TerminateProcess() with an access
error, and I've seen random extra python processes hanging around after running
tests sometimes, so this might help.

However, e48cb1c7a902 forces this change.  Since the pid object is no longer
converted to a string, the cmd.exe pid was being saved instead of the hg pid,
and none of the daemons were being killed.

diff --git a/mercurial/win32.py b/mercurial/win32.py
--- a/mercurial/win32.py
+++ b/mercurial/win32.py
@@ -134,27 +134,6 @@
 _STD_OUTPUT_HANDLE = _DWORD(-11).value
 _STD_ERROR_HANDLE = _DWORD(-12).value
 
-# CreateToolhelp32Snapshot, Process32First, Process32Next
-_TH32CS_SNAPPROCESS = 0x00000002
-_MAX_PATH = 260
-
-class _tagPROCESSENTRY32(ctypes.Structure):
-    _fields_ = [('dwsize', _DWORD),
-                ('cntUsage', _DWORD),
-                ('th32ProcessID', _DWORD),
-                ('th32DefaultHeapID', ctypes.c_void_p),
-                ('th32ModuleID', _DWORD),
-                ('cntThreads', _DWORD),
-                ('th32ParentProcessID', _DWORD),
-                ('pcPriClassBase', _LONG),
-                ('dwFlags', _DWORD),
-                ('szExeFile', ctypes.c_char * _MAX_PATH)]
-
-    def __init__(self):
-        super(_tagPROCESSENTRY32, self).__init__()
-        self.dwsize = ctypes.sizeof(self)
-
-
 # types of parameters of C functions used (required by pypy)
 
 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
@@ -228,19 +207,10 @@
 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
 _user32.EnumWindows.restype = _BOOL
 
-_kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
-_kernel32.CreateToolhelp32Snapshot.restype = _BOOL
-
 _kernel32.PeekNamedPipe.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD,
     ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
 _kernel32.PeekNamedPipe.restype = _BOOL
 
-_kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
-_kernel32.Process32First.restype = _BOOL
-
-_kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
-_kernel32.Process32Next.restype = _BOOL
-
 def _raiseoserror(name):
     err = ctypes.WinError()
     raise OSError(err.errno, '%s: %s' % (name, err.strerror))
@@ -402,51 +372,6 @@
 
     return True
 
-def _1stchild(pid):
-    '''return the 1st found child of the given pid
-
-    None is returned when no child is found'''
-    pe = _tagPROCESSENTRY32()
-
-    # create handle to list all processes
-    ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
-    if ph == _INVALID_HANDLE_VALUE:
-        raise ctypes.WinError()
-    try:
-        r = _kernel32.Process32First(ph, ctypes.byref(pe))
-        # loop over all processes
-        while r:
-            if pe.th32ParentProcessID == pid:
-                # return first child found
-                return pe.th32ProcessID
-            r = _kernel32.Process32Next(ph, ctypes.byref(pe))
-    finally:
-        _kernel32.CloseHandle(ph)
-    if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
-        raise ctypes.WinError()
-    return None # no child found
-
-class _tochildpid(int): # pid is _DWORD, which always matches in an int
-    '''helper for spawndetached, returns the child pid on conversion to string
-
-    Does not resolve the child pid immediately because the child may not yet be
-    started.
-    '''
-    def childpid(self):
-        '''returns the child pid of the first found child of the process
-        with this pid'''
-        return _1stchild(self)
-    def __str__(self):
-        # run when the pid is written to the file
-        ppid = self.childpid()
-        if ppid is None:
-            # race, child has exited since check
-            # fall back to this pid. Its process will also have disappeared,
-            # raising the same error type later as when the child pid would
-            # be returned.
-            return " %d" % self
-        return str(ppid)
-
 def spawndetached(args):
     # No standard library function really spawns a fully detached
     # process under win32 because they allocate pipes or other objects
@@ -466,10 +391,6 @@
     env += '\0'
 
     args = subprocess.list2cmdline(args)
-    # Not running the command in shell mode makes Python 2.6 hang when
-    # writing to hgweb output socket.
-    comspec = encoding.environ.get("COMSPEC", "cmd.exe")
-    args = comspec + " /c " + args
 
     res = _kernel32.CreateProcessA(
         None, args, None, None, False, _CREATE_NO_WINDOW,
@@ -477,8 +398,7 @@
     if not res:
         raise ctypes.WinError()
 
-    # _tochildpid because the process is the child of COMSPEC
-    return _tochildpid(pi.dwProcessId)
+    return pi.dwProcessId
 
 def unlink(f):
     '''try to implement POSIX' unlink semantics on Windows'''


More information about the Mercurial-devel mailing list