tests: import killdaemons.py from Mercurial 1cfded2fa1a9
This contains updated functionality to kill the server process on Windows, which
is needed to run the test-*server.t tests. This version requires the pids to be
passed as an argument instead of via $DAEMON_PIDS.
--- a/tests/killdaemons.py Fri Mar 20 12:51:57 2015 -0700
+++ b/tests/killdaemons.py Sat Mar 21 18:42:51 2015 -0400
@@ -1,25 +1,91 @@
#!/usr/bin/env python
-import os, time, errno, signal
+import os, sys, time, errno, signal
+
+if os.name =='nt':
+ import ctypes
+
+ def _check(ret, expectederr=None):
+ if ret == 0:
+ winerrno = ctypes.GetLastError()
+ if winerrno == expectederr:
+ return True
+ raise ctypes.WinError(winerrno)
-# Kill off any leftover daemon processes
-try:
- fp = open(os.environ['DAEMON_PIDS'])
- for line in fp:
+ 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
+ handle = ctypes.windll.kernel32.OpenProcess(
+ PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
+ False, pid)
+ if handle == 0:
+ _check(0, 87) # err 87 when process not found
+ return # process not found, already finished
try:
- pid = int(line)
- except ValueError:
- continue
+ 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))
+ else:
+ _check(r)
+
+ # 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')
+ else:
+ _check(r) # any error
+ 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)
- for i in range(10):
- time.sleep(0.05)
+ 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, err:
if err.errno != errno.ESRCH:
raise
- fp.close()
-except IOError:
- pass
+
+def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
+ if not logfn:
+ logfn = lambda s: s
+ # Kill off any leftover daemon processes
+ try:
+ fp = open(pidfile)
+ for line in fp:
+ try:
+ pid = int(line)
+ except ValueError:
+ continue
+ kill(pid, logfn, tryhard)
+ fp.close()
+ if remove:
+ os.unlink(pidfile)
+ except IOError:
+ pass
+
+if __name__ == '__main__':
+ path, = sys.argv[1:]
+ killdaemons(path)
--- a/tests/test-simple4server-bundle2.t Fri Mar 20 12:51:57 2015 -0700
+++ b/tests/test-simple4server-bundle2.t Sat Mar 21 18:42:51 2015 -0400
@@ -140,7 +140,7 @@
$ echo '[__temporary__]' >> server/.hg/hgrc
$ echo 'advertiseobsolete=False' >> server/.hg/hgrc
- $ $TESTDIR/killdaemons.py
+ $ $TESTDIR/killdaemons.py $DAEMON_PIDS
$ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
$ cat hg.pid >> $DAEMON_PIDS
@@ -154,7 +154,7 @@
lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2-exp=HG2Y%0Ab2x%253Achangegroup%3D01%2C02%0Ab2x%253Alistkeys%0Ab2x%253Aobsmarkers%3DV0%2CV1%0Ab2x%253Apushkey%0Ab2x%253Aremote-changegroup%3Dhttp%2Chttps%0Adigests%3Dmd5%2Csha1%2Csha512 unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 (no-eol)
$ echo 'advertiseobsolete=True' >> server/.hg/hgrc
- $ $TESTDIR/killdaemons.py
+ $ $TESTDIR/killdaemons.py $DAEMON_PIDS
$ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
$ cat hg.pid >> $DAEMON_PIDS
--- a/tests/test-simple4server.t Fri Mar 20 12:51:57 2015 -0700
+++ b/tests/test-simple4server.t Sat Mar 21 18:42:51 2015 -0400
@@ -141,7 +141,7 @@
$ echo '[__temporary__]' >> server/.hg/hgrc
$ echo 'advertiseobsolete=False' >> server/.hg/hgrc
- $ $TESTDIR/killdaemons.py
+ $ $TESTDIR/killdaemons.py $DAEMON_PIDS
$ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
$ cat hg.pid >> $DAEMON_PIDS
@@ -155,7 +155,7 @@
lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 (no-eol)
$ echo 'advertiseobsolete=True' >> server/.hg/hgrc
- $ $TESTDIR/killdaemons.py
+ $ $TESTDIR/killdaemons.py $DAEMON_PIDS
$ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
$ cat hg.pid >> $DAEMON_PIDS