Mercurial > hg
view tests/killdaemons.py @ 40432:968dd7e02ac5
changegroup: allow to force delta to be against p1
This new developer option is useful to general more "generic" bundle. Without
this option, a bundle generated from the repository use deltas similar to the
one stored in the specific repository it was generated from. This makes
performance testing a bit tricky.
Using deltas similar to the final result means all delta stored in the bundle
can be applied to the target repository without any further processing (except
for the rare case of a full snapshot). The application of such bundles
(almost) never exercises the (slower) path of searching for a new valid delta.
This result in unrealistic and too favorable timing and profile.
Instead, we introduce an option to make sure all revisions are stored as a
delta against p1. It might not be the best generation option, but it
guarantees that the content will be "generic", not favoring a specific target.
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Wed, 10 Oct 2018 00:21:02 +0200 |
parents | 89793289c891 |
children | 2372284d9457 |
line wrap: on
line source
#!/usr/bin/env python from __future__ import absolute_import import errno import os import signal import sys import time if os.name =='nt': import ctypes _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 def _check(ret, expectederr=None): if ret == 0: winerrno = ctypes.GetLastError() if winerrno == expectederr: return True raise ctypes.WinError(winerrno) def kill(pid, logfn, tryhard=True): logfn('# Killing daemon process %d' % pid) PROCESS_TERMINATE = 1 PROCESS_QUERY_INFORMATION = 0x400 SYNCHRONIZE = 0x00100000 WAIT_OBJECT_0 = 0 WAIT_TIMEOUT = 258 WAIT_FAILED = _DWORD(0xFFFFFFFF).value handle = ctypes.windll.kernel32.OpenProcess( PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION, False, pid) if handle is None: _check(0, 87) # err 87 when process not found return # process not found, already finished try: 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)) elif r == WAIT_FAILED: _check(0) # err stored in GetLastError() # 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') elif r == WAIT_FAILED: _check(0) # err stored in GetLastError() except: #re-raises ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error raise _check(ctypes.windll.kernel32.CloseHandle(handle)) 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) except OSError as err: if err.errno != errno.ESRCH: raise def killdaemons(pidfile, tryhard=True, remove=False, logfn=None): if not logfn: logfn = lambda s: s # Kill off any leftover daemon processes try: 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: kill(pid, logfn, tryhard) if remove: os.unlink(pidfile) except IOError: pass if __name__ == '__main__': if len(sys.argv) > 1: path, = sys.argv[1:] else: path = os.environ["DAEMON_PIDS"] killdaemons(path, remove=True)