mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
a6fdd0b148
When I was fixing the test-gpg issue, I noticed gpg-connect-agent could print "-1" as a server pid if command was wrong. I'm not pretty sure but nobody would want to kill their running applications by mistake.
105 lines
3.3 KiB
Python
Executable File
105 lines
3.3 KiB
Python
Executable File
#!/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
|
|
|
|
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
|
|
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:
|
|
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)
|
|
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:
|
|
fp = open(pidfile)
|
|
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
|
|
kill(pid, logfn, tryhard)
|
|
fp.close()
|
|
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)
|