##// END OF EJS Templates
win32: spawndetached returns pid of detached process and not of cmd.exe...
Simon Heimberg -
r20425:ca6aa836 default
parent child Browse files
Show More
@@ -119,6 +119,27 b' class _CONSOLE_SCREEN_BUFFER_INFO(ctypes'
119 119
120 120 _STD_ERROR_HANDLE = _DWORD(-12).value
121 121
122 # CreateToolhelp32Snapshot, Process32First, Process32Next
123 _TH32CS_SNAPPROCESS = 0x00000002
124 _MAX_PATH = 260
125
126 class _tagPROCESSENTRY32(ctypes.Structure):
127 _fields_ = [('dwsize', _DWORD),
128 ('cntUsage', _DWORD),
129 ('th32ProcessID', _DWORD),
130 ('th32DefaultHeapID', ctypes.c_void_p),
131 ('th32ModuleID', _DWORD),
132 ('cntThreads', _DWORD),
133 ('th32ParentProcessID', _DWORD),
134 ('pcPriClassBase', _LONG),
135 ('dwFlags', _DWORD),
136 ('szExeFile', ctypes.c_char * _MAX_PATH)]
137
138 def __init__(self):
139 super(_tagPROCESSENTRY32, self).__init__()
140 self.dwsize = ctypes.sizeof(self)
141
142
122 143 # types of parameters of C functions used (required by pypy)
123 144
124 145 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
@@ -186,6 +207,15 b' except AttributeError:'
186 207 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
187 208 _user32.EnumWindows.restype = _BOOL
188 209
210 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
211 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
212
213 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
214 _kernel32.Process32First.restype = _BOOL
215
216 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
217 _kernel32.Process32Next.restype = _BOOL
218
189 219 def _raiseoserror(name):
190 220 err = ctypes.WinError()
191 221 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
@@ -309,6 +339,51 b' def termwidth():'
309 339 width = csbi.srWindow.Right - csbi.srWindow.Left
310 340 return width
311 341
342 def _1stchild(pid):
343 '''return the 1st found child of the given pid
344
345 None is returned when no child is found'''
346 pe = _tagPROCESSENTRY32()
347
348 # create handle to list all processes
349 ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
350 if ph == _INVALID_HANDLE_VALUE:
351 raise ctypes.WinError
352 try:
353 r = _kernel32.Process32First(ph, ctypes.byref(pe))
354 # loop over all processes
355 while r:
356 if pe.th32ParentProcessID == pid:
357 # return first child found
358 return pe.th32ProcessID
359 r = _kernel32.Process32Next(ph, ctypes.byref(pe))
360 finally:
361 _kernel32.CloseHandle(ph)
362 if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
363 raise ctypes.WinError
364 return None # no child found
365
366 class _tochildpid(int): # pid is _DWORD, which always matches in an int
367 '''helper for spawndetached, returns the child pid on conversion to string
368
369 Does not resolve the child pid immediately because the child may not yet be
370 started.
371 '''
372 def childpid(self):
373 '''returns the child pid of the first found child of the process
374 with this pid'''
375 return _1stchild(self)
376 def __str__(self):
377 # run when the pid is written to the file
378 ppid = self.childpid()
379 if ppid is None:
380 # race, child has exited since check
381 # fall back to this pid. Its process will also have disappeared,
382 # raising the same error type later as when the child pid would
383 # be returned.
384 return " %d" % self
385 return str(ppid)
386
312 387 def spawndetached(args):
313 388 # No standard library function really spawns a fully detached
314 389 # process under win32 because they allocate pipes or other objects
@@ -339,7 +414,8 b' def spawndetached(args):'
339 414 if not res:
340 415 raise ctypes.WinError
341 416
342 return pi.dwProcessId
417 # _tochildpid because the process is the child of COMSPEC
418 return _tochildpid(pi.dwProcessId)
343 419
344 420 def unlink(f):
345 421 '''try to implement POSIX' unlink semantics on Windows'''
General Comments 0
You need to be logged in to leave comments. Login now