##// END OF EJS Templates
killdaemons: close pid file before killing processes...
Matt Harbison -
r32677:f840b262 default
parent child Browse files
Show More
@@ -1,104 +1,106 b''
1 1 #!/usr/bin/env python
2 2
3 3 from __future__ import absolute_import
4 4 import errno
5 5 import os
6 6 import signal
7 7 import sys
8 8 import time
9 9
10 10 if os.name =='nt':
11 11 import ctypes
12 12
13 13 def _check(ret, expectederr=None):
14 14 if ret == 0:
15 15 winerrno = ctypes.GetLastError()
16 16 if winerrno == expectederr:
17 17 return True
18 18 raise ctypes.WinError(winerrno)
19 19
20 20 def kill(pid, logfn, tryhard=True):
21 21 logfn('# Killing daemon process %d' % pid)
22 22 PROCESS_TERMINATE = 1
23 23 PROCESS_QUERY_INFORMATION = 0x400
24 24 SYNCHRONIZE = 0x00100000
25 25 WAIT_OBJECT_0 = 0
26 26 WAIT_TIMEOUT = 258
27 27 handle = ctypes.windll.kernel32.OpenProcess(
28 28 PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
29 29 False, pid)
30 30 if handle == 0:
31 31 _check(0, 87) # err 87 when process not found
32 32 return # process not found, already finished
33 33 try:
34 34 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
35 35 if r == WAIT_OBJECT_0:
36 36 pass # terminated, but process handle still available
37 37 elif r == WAIT_TIMEOUT:
38 38 _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
39 39 else:
40 40 _check(r)
41 41
42 42 # TODO?: forcefully kill when timeout
43 43 # and ?shorter waiting time? when tryhard==True
44 44 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
45 45 # timeout = 100 ms
46 46 if r == WAIT_OBJECT_0:
47 47 pass # process is terminated
48 48 elif r == WAIT_TIMEOUT:
49 49 logfn('# Daemon process %d is stuck')
50 50 else:
51 51 _check(r) # any error
52 52 except: #re-raises
53 53 ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
54 54 raise
55 55 _check(ctypes.windll.kernel32.CloseHandle(handle))
56 56
57 57 else:
58 58 def kill(pid, logfn, tryhard=True):
59 59 try:
60 60 os.kill(pid, 0)
61 61 logfn('# Killing daemon process %d' % pid)
62 62 os.kill(pid, signal.SIGTERM)
63 63 if tryhard:
64 64 for i in range(10):
65 65 time.sleep(0.05)
66 66 os.kill(pid, 0)
67 67 else:
68 68 time.sleep(0.1)
69 69 os.kill(pid, 0)
70 70 logfn('# Daemon process %d is stuck - really killing it' % pid)
71 71 os.kill(pid, signal.SIGKILL)
72 72 except OSError as err:
73 73 if err.errno != errno.ESRCH:
74 74 raise
75 75
76 76 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
77 77 if not logfn:
78 78 logfn = lambda s: s
79 79 # Kill off any leftover daemon processes
80 80 try:
81 fp = open(pidfile)
82 for line in fp:
83 try:
84 pid = int(line)
85 if pid <= 0:
86 raise ValueError
87 except ValueError:
88 logfn('# Not killing daemon process %s - invalid pid'
89 % line.rstrip())
90 continue
81 pids = []
82 with open(pidfile) as fp:
83 for line in fp:
84 try:
85 pid = int(line)
86 if pid <= 0:
87 raise ValueError
88 except ValueError:
89 logfn('# Not killing daemon process %s - invalid pid'
90 % line.rstrip())
91 continue
92 pids.append(pid)
93 for pid in pids:
91 94 kill(pid, logfn, tryhard)
92 fp.close()
93 95 if remove:
94 96 os.unlink(pidfile)
95 97 except IOError:
96 98 pass
97 99
98 100 if __name__ == '__main__':
99 101 if len(sys.argv) > 1:
100 102 path, = sys.argv[1:]
101 103 else:
102 104 path = os.environ["DAEMON_PIDS"]
103 105
104 106 killdaemons(path)
General Comments 0
You need to be logged in to leave comments. Login now