##// END OF EJS Templates
tests: stabilize `test-merge-partial-tool.t` on Windows...
tests: stabilize `test-merge-partial-tool.t` on Windows The test was previously failing because it was opening the shell scripts being used as an executable in a text editor, and problems cascaded from there.

File last commit:

r52596:ca7bde5d default
r52838:4ee2505f default
Show More
killdaemons.py
131 lines | 4.2 KiB | text/x-python | PythonLexer
Gregory Szorc
global: use python3 in shebangs...
r46434 #!/usr/bin/env python3
Matt Mackall
tests: add killdaemons helper script
r7344
Robert Stanca
py3: use absolute_import in killdaemons.py
r28942 import os
import signal
import sys
import time
Matt Mackall
tests: add killdaemons helper script
r7344
Augie Fackler
formatting: blacken the codebase...
r43346 if os.name == 'nt':
Patrick Mezard
killdaemons: add windows implementation
r17465 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(
Augie Fackler
formatting: blacken the codebase...
r43346 PROCESS_TERMINATE | SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
False,
pid,
)
Matt Harbison
killdaemons: explicitly set the ctypes signatures...
r32857 if handle is None:
Augie Fackler
formatting: blacken the codebase...
r43346 _check(0, 87) # err 87 when process not found
return # process not found, already finished
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493 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:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # terminated, but process handle still available
Simon Heimberg
tests: killdaemons.py for windows distinguishes access violation and terminated...
r20496 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)
Augie Fackler
formatting: blacken the codebase...
r43346 # timeout = 100 ms
Simon Heimberg
tests: killdaemons.py for windows waits for killed process to terminate...
r20494 if r == WAIT_OBJECT_0:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # process is terminated
Simon Heimberg
tests: killdaemons.py for windows waits for killed process to terminate...
r20494 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()
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises
ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
Simon Heimberg
tests: kill for windows in killdaemons.py checks return values...
r20493 raise
_check(ctypes.windll.kernel32.CloseHandle(handle))
Patrick Mezard
killdaemons: add windows implementation
r17465 else:
Augie Fackler
formatting: blacken the codebase...
r43346
Patrick Mezard
killdaemons: add windows implementation
r17465 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)
Manuel Jacob
py3: catch ProcessLookupError instead of checking errno == ESRCH
r50204 except ProcessLookupError:
pass
Patrick Mezard
killdaemons: add windows implementation
r17465
Augie Fackler
formatting: blacken the codebase...
r43346
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:
Augie Fackler
formatting: blacken the codebase...
r43346 logfn(
'# Not killing daemon process %s - invalid pid'
% line.rstrip()
)
Matt Harbison
killdaemons: close pid file before killing processes...
r32677 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
Augie Fackler
formatting: blacken the codebase...
r43346
Patrick Mezard
run-tests: do not duplicate killdaemons() code
r17464 if __name__ == '__main__':
Matt Mackall
tests: make killdaemons.py use DAEMON_PIDS by default
r25473 if len(sys.argv) > 1:
Augie Fackler
formatting: blacken the codebase...
r43346 (path,) = sys.argv[1:]
Matt Mackall
tests: make killdaemons.py use DAEMON_PIDS by default
r25473 else:
path = os.environ["DAEMON_PIDS"]
Gregory Szorc
tests: remove pid file by default...
r37865 killdaemons(path, remove=True)