44 SYNCHRONIZE = 0x00100000 |
44 SYNCHRONIZE = 0x00100000 |
45 WAIT_OBJECT_0 = 0 |
45 WAIT_OBJECT_0 = 0 |
46 WAIT_TIMEOUT = 258 |
46 WAIT_TIMEOUT = 258 |
47 WAIT_FAILED = _DWORD(0xFFFFFFFF).value |
47 WAIT_FAILED = _DWORD(0xFFFFFFFF).value |
48 handle = ctypes.windll.kernel32.OpenProcess( |
48 handle = ctypes.windll.kernel32.OpenProcess( |
49 PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION, |
49 PROCESS_TERMINATE | SYNCHRONIZE | PROCESS_QUERY_INFORMATION, |
50 False, pid) |
50 False, |
|
51 pid, |
|
52 ) |
51 if handle is None: |
53 if handle is None: |
52 _check(0, 87) # err 87 when process not found |
54 _check(0, 87) # err 87 when process not found |
53 return # process not found, already finished |
55 return # process not found, already finished |
54 try: |
56 try: |
55 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100) |
57 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100) |
56 if r == WAIT_OBJECT_0: |
58 if r == WAIT_OBJECT_0: |
57 pass # terminated, but process handle still available |
59 pass # terminated, but process handle still available |
58 elif r == WAIT_TIMEOUT: |
60 elif r == WAIT_TIMEOUT: |
59 _check(ctypes.windll.kernel32.TerminateProcess(handle, -1)) |
61 _check(ctypes.windll.kernel32.TerminateProcess(handle, -1)) |
60 elif r == WAIT_FAILED: |
62 elif r == WAIT_FAILED: |
61 _check(0) # err stored in GetLastError() |
63 _check(0) # err stored in GetLastError() |
62 |
64 |
63 # TODO?: forcefully kill when timeout |
65 # TODO?: forcefully kill when timeout |
64 # and ?shorter waiting time? when tryhard==True |
66 # and ?shorter waiting time? when tryhard==True |
65 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100) |
67 r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100) |
66 # timeout = 100 ms |
68 # timeout = 100 ms |
67 if r == WAIT_OBJECT_0: |
69 if r == WAIT_OBJECT_0: |
68 pass # process is terminated |
70 pass # process is terminated |
69 elif r == WAIT_TIMEOUT: |
71 elif r == WAIT_TIMEOUT: |
70 logfn('# Daemon process %d is stuck') |
72 logfn('# Daemon process %d is stuck') |
71 elif r == WAIT_FAILED: |
73 elif r == WAIT_FAILED: |
72 _check(0) # err stored in GetLastError() |
74 _check(0) # err stored in GetLastError() |
73 except: #re-raises |
75 except: # re-raises |
74 ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error |
76 ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error |
75 raise |
77 raise |
76 _check(ctypes.windll.kernel32.CloseHandle(handle)) |
78 _check(ctypes.windll.kernel32.CloseHandle(handle)) |
77 |
79 |
|
80 |
78 else: |
81 else: |
|
82 |
79 def kill(pid, logfn, tryhard=True): |
83 def kill(pid, logfn, tryhard=True): |
80 try: |
84 try: |
81 os.kill(pid, 0) |
85 os.kill(pid, 0) |
82 logfn('# Killing daemon process %d' % pid) |
86 logfn('# Killing daemon process %d' % pid) |
83 os.kill(pid, signal.SIGTERM) |
87 os.kill(pid, signal.SIGTERM) |
92 os.kill(pid, signal.SIGKILL) |
96 os.kill(pid, signal.SIGKILL) |
93 except OSError as err: |
97 except OSError as err: |
94 if err.errno != errno.ESRCH: |
98 if err.errno != errno.ESRCH: |
95 raise |
99 raise |
96 |
100 |
|
101 |
97 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None): |
102 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None): |
98 if not logfn: |
103 if not logfn: |
99 logfn = lambda s: s |
104 logfn = lambda s: s |
100 # Kill off any leftover daemon processes |
105 # Kill off any leftover daemon processes |
101 try: |
106 try: |
105 try: |
110 try: |
106 pid = int(line) |
111 pid = int(line) |
107 if pid <= 0: |
112 if pid <= 0: |
108 raise ValueError |
113 raise ValueError |
109 except ValueError: |
114 except ValueError: |
110 logfn('# Not killing daemon process %s - invalid pid' |
115 logfn( |
111 % line.rstrip()) |
116 '# Not killing daemon process %s - invalid pid' |
|
117 % line.rstrip() |
|
118 ) |
112 continue |
119 continue |
113 pids.append(pid) |
120 pids.append(pid) |
114 for pid in pids: |
121 for pid in pids: |
115 kill(pid, logfn, tryhard) |
122 kill(pid, logfn, tryhard) |
116 if remove: |
123 if remove: |
117 os.unlink(pidfile) |
124 os.unlink(pidfile) |
118 except IOError: |
125 except IOError: |
119 pass |
126 pass |
120 |
127 |
|
128 |
121 if __name__ == '__main__': |
129 if __name__ == '__main__': |
122 if len(sys.argv) > 1: |
130 if len(sys.argv) > 1: |
123 path, = sys.argv[1:] |
131 (path,) = sys.argv[1:] |
124 else: |
132 else: |
125 path = os.environ["DAEMON_PIDS"] |
133 path = os.environ["DAEMON_PIDS"] |
126 |
134 |
127 killdaemons(path, remove=True) |
135 killdaemons(path, remove=True) |