##// END OF EJS Templates
tests: use () instead of \ to wrap lines...
tests: use () instead of \ to wrap lines This should auto-format more consistently, and is slightly more typical Python. Differential Revision: https://phab.mercurial-scm.org/D5992

File last commit:

r37865:89793289 default
r41924:15d3facf default
Show More
killdaemons.py
127 lines | 4.2 KiB | text/x-python | PythonLexer
Matt Mackall
tests: add killdaemons helper script
r7344 #!/usr/bin/env python
Robert Stanca
py3: use absolute_import in killdaemons.py
r28942 from __future__ import absolute_import
import errno
import os
import signal
import sys
import time
Matt Mackall
tests: add killdaemons helper script
r7344
Patrick Mezard
killdaemons: add windows implementation
r17465 if os.name =='nt':
import ctypes
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493
Matt Harbison
killdaemons: explicitly set the ctypes signatures...
r32857 _BOOL = ctypes.c_long
_DWORD = ctypes.c_ulong
_UINT = ctypes.c_uint
_HANDLE = ctypes.c_void_p
ctypes.windll.kernel32.CloseHandle.argtypes = [_HANDLE]
ctypes.windll.kernel32.CloseHandle.restype = _BOOL
ctypes.windll.kernel32.GetLastError.argtypes = []
ctypes.windll.kernel32.GetLastError.restype = _DWORD
ctypes.windll.kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
ctypes.windll.kernel32.OpenProcess.restype = _HANDLE
ctypes.windll.kernel32.TerminateProcess.argtypes = [_HANDLE, _UINT]
ctypes.windll.kernel32.TerminateProcess.restype = _BOOL
ctypes.windll.kernel32.WaitForSingleObject.argtypes = [_HANDLE, _DWORD]
ctypes.windll.kernel32.WaitForSingleObject.restype = _DWORD
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493 def _check(ret, expectederr=None):
if ret == 0:
winerrno = ctypes.GetLastError()
if winerrno == expectederr:
return True
raise ctypes.WinError(winerrno)
Patrick Mezard
killdaemons: add windows implementation
r17465 def kill(pid, logfn, tryhard=True):
logfn('# Killing daemon process %d' % pid)
PROCESS_TERMINATE = 1
Simon Heimberg
tests: killdaemons.py for windows distinguishes access violation and terminated...
r20496 PROCESS_QUERY_INFORMATION = 0x400
Augie Fackler
killdaemons: drop superfluous L suffix from constant...
r20698 SYNCHRONIZE = 0x00100000
Simon Heimberg
tests: killdaemons.py for windows waits for killed process to terminate...
r20494 WAIT_OBJECT_0 = 0
WAIT_TIMEOUT = 258
Matt Harbison
killdaemons: fix WaitForSingleObject() error handling logic on Windows...
r32858 WAIT_FAILED = _DWORD(0xFFFFFFFF).value
Patrick Mezard
killdaemons: add windows implementation
r17465 handle = ctypes.windll.kernel32.OpenProcess(
Simon Heimberg
tests: killdaemons.py for windows distinguishes access violation and terminated...
r20496 PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
False, pid)
Matt Harbison
killdaemons: explicitly set the ctypes signatures...
r32857 if handle is None:
Simon Heimberg
tests: killdaemons.py for checks reason when getting no process handle
r20495 _check(0, 87) # err 87 when process not found
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493 return # process not found, already finished
try:
Simon Heimberg
tests: killdaemons.py for windows distinguishes access violation and terminated...
r20496 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
if r == WAIT_OBJECT_0:
pass # terminated, but process handle still available
elif r == WAIT_TIMEOUT:
_check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
Matt Harbison
killdaemons: fix WaitForSingleObject() error handling logic on Windows...
r32858 elif r == WAIT_FAILED:
_check(0) # err stored in GetLastError()
Simon Heimberg
tests: killdaemons.py for windows waits for killed process to terminate...
r20494
# TODO?: forcefully kill when timeout
# and ?shorter waiting time? when tryhard==True
r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
# timeout = 100 ms
if r == WAIT_OBJECT_0:
pass # process is terminated
elif r == WAIT_TIMEOUT:
logfn('# Daemon process %d is stuck')
Matt Harbison
killdaemons: fix WaitForSingleObject() error handling logic on Windows...
r32858 elif r == WAIT_FAILED:
_check(0) # err stored in GetLastError()
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493 except: #re-raises
ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
raise
_check(ctypes.windll.kernel32.CloseHandle(handle))
Patrick Mezard
killdaemons: add windows implementation
r17465 else:
def kill(pid, logfn, tryhard=True):
try:
os.kill(pid, 0)
logfn('# Killing daemon process %d' % pid)
os.kill(pid, signal.SIGTERM)
if tryhard:
for i in range(10):
time.sleep(0.05)
os.kill(pid, 0)
else:
time.sleep(0.1)
os.kill(pid, 0)
logfn('# Daemon process %d is stuck - really killing it' % pid)
os.kill(pid, signal.SIGKILL)
Augie Fackler
python3: update killdaemons and run-tests print and exception syntax...
r25031 except OSError as err:
Patrick Mezard
killdaemons: add windows implementation
r17465 if err.errno != errno.ESRCH:
raise
Patrick Mezard
run-tests: do not duplicate killdaemons() code
r17464 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
if not logfn:
logfn = lambda s: s
# Kill off any leftover daemon processes
try:
Matt Harbison
killdaemons: close pid file before killing processes...
r32677 pids = []
with open(pidfile) as fp:
for line in fp:
try:
pid = int(line)
if pid <= 0:
raise ValueError
except ValueError:
logfn('# Not killing daemon process %s - invalid pid'
% line.rstrip())
continue
pids.append(pid)
for pid in pids:
Patrick Mezard
killdaemons: add windows implementation
r17465 kill(pid, logfn, tryhard)
Patrick Mezard
run-tests: do not duplicate killdaemons() code
r17464 if remove:
os.unlink(pidfile)
except IOError:
pass
if __name__ == '__main__':
Matt Mackall
tests: make killdaemons.py use DAEMON_PIDS by default
r25473 if len(sys.argv) > 1:
path, = sys.argv[1:]
else:
path = os.environ["DAEMON_PIDS"]
Gregory Szorc
tests: remove pid file by default...
r37865 killdaemons(path, remove=True)