Flutter Engine
The Flutter Engine
task_kill.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2#
3# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
4# for details. All rights reserved. Use of this source code is governed by a
5# BSD-style license that can be found in the LICENSE file.
6#
7
8# A script to kill hanging process. The tool will return non-zero if any
9# process was actually found.
10#
11
12import optparse
13import os
14import signal
15import subprocess
16import sys
17
18import utils
19
20os_name = utils.GuessOS()
21
22POSIX_INFO = 'ps -p %s -o args'
23
24EXECUTABLE_NAMES = {
25 'win32': {
26 'chrome': 'chrome.exe',
27 'dart': 'dart.exe',
28 'dartaotruntime': 'dartaotruntime.exe',
29 'dart_precompiled_runtime': 'dart_precompiled_runtime.exe',
30 'firefox': 'firefox.exe',
31 'gen_snapshot': 'gen_snapshot.exe',
32 'git': 'git.exe',
33 'iexplore': 'iexplore.exe',
34 'vctip': 'vctip.exe',
35 'mspdbsrv': 'mspdbsrv.exe',
36 },
37 'linux': {
38 'chrome': 'chrome',
39 'dart': 'dart',
40 'dartaotruntime': 'dartaotruntime',
41 'dart_precompiled_runtime': 'dart_precompiled_runtime',
42 'firefox': 'firefox',
43 'gen_snapshot': 'gen_snapshot',
44 'flutter_tester': 'flutter_tester',
45 'git': 'git',
46 },
47 'macos': {
48 'chrome': 'Chrome',
49 'chrome_helper': 'Chrome Helper',
50 'dart': 'dart',
51 'dartaotruntime': 'dartaotruntime',
52 'dart_precompiled_runtime': 'dart_precompiled_runtime',
53 'firefox': 'firefox',
54 'gen_snapshot': 'gen_snapshot',
55 'git': 'git',
56 'safari': 'Safari',
57 }
58}
59
60INFO_COMMAND = {
61 'win32': 'wmic process where Processid=%s get CommandLine',
62 'macos': POSIX_INFO,
63 'linux': POSIX_INFO,
64}
65
66STACK_INFO_COMMAND = {
67 'win32': None,
68 'macos': '/usr/bin/sample %s 1 4000 -mayDie',
69 'linux': '/usr/bin/eu-stack -p %s',
70}
71
72
74 parser = optparse.OptionParser('usage: %prog [options]')
75 true_or_false = ['True', 'False']
76 parser.add_option(
77 "--kill_dart",
78 default='True',
79 type='choice',
80 choices=true_or_false,
81 help="Kill all dart processes")
82 parser.add_option(
83 "--kill_vc",
84 default='True',
85 type='choice',
86 choices=true_or_false,
87 help="Kill all git processes")
88 parser.add_option(
89 "--kill_vsbuild",
90 default='False',
91 type='choice',
92 choices=true_or_false,
93 help="Kill all visual studio build related processes")
94 parser.add_option(
95 "--kill_browsers",
96 default='False',
97 type='choice',
98 choices=true_or_false,
99 help="Kill all browser processes")
100 (options, args) = parser.parse_args()
101 return options
102
103
104def GetPidsPosix(process_name):
105 # This is to have only one posix command, on linux we could just do:
106 # pidof process_name
107 cmd = 'ps -e -o pid= -o comm='
108 # Sample output:
109 # 1 /sbin/launchd
110 # 80943 /Applications/Safari.app/Contents/MacOS/Safari
111 p = subprocess.Popen(cmd,
112 stdout=subprocess.PIPE,
113 stderr=subprocess.PIPE,
114 shell=True,
115 universal_newlines=True)
116 output, stderr = p.communicate()
117 results = []
118 lines = output.splitlines()
119 for line in lines:
120 split = line.split()
121 # On mac this ps commands actually gives us the full path to non
122 # system binaries.
123 if len(split) >= 2 and " ".join(split[1:]).endswith(process_name):
124 results.append(split[0])
125 return results
126
127
128def GetPidsWindows(process_name):
129 cmd = 'tasklist /FI "IMAGENAME eq %s" /NH' % process_name
130 # Sample output:
131 # dart.exe 4356 Console 1 6,800 K
132 p = subprocess.Popen(cmd,
133 stdout=subprocess.PIPE,
134 stderr=subprocess.PIPE,
135 shell=True,
136 universal_newlines=True)
137 output, stderr = p.communicate()
138 results = []
139 lines = output.splitlines()
140
141 for line in lines:
142 split = line.split()
143 if len(split) > 2 and split[0] == process_name:
144 results.append(split[1])
145 return results
146
147
148def GetPids(process_name):
149 if os_name == "win32":
150 return GetPidsWindows(process_name)
151 else:
152 return GetPidsPosix(process_name)
153
154
156 command_pattern = STACK_INFO_COMMAND.get(os_name, False)
157 if command_pattern:
158 p = subprocess.Popen(command_pattern % pid,
159 stdout=subprocess.PIPE,
160 stderr=subprocess.PIPE,
161 shell=True,
162 universal_newlines=True)
163 stdout, stderr = p.communicate()
164 stdout = stdout.splitlines()
165 stderr = stderr.splitlines()
166
167 print(" Stack:")
168 for line in stdout:
169 print(" %s" % line)
170 if stderr:
171 print(" Stack (stderr):")
172 for line in stderr:
173 print(" %s" % line)
174
175
176def PrintPidInfo(pid, dump_stacks):
177 # We assume that the list command will return lines in the format:
178 # EXECUTABLE_PATH ARGS
179 # There may be blank strings in the output
180 p = subprocess.Popen(INFO_COMMAND[os_name] % pid,
181 stdout=subprocess.PIPE,
182 stderr=subprocess.PIPE,
183 shell=True,
184 universal_newlines=True)
185 output, stderr = p.communicate()
186 lines = output.splitlines()
187
188 # Pop the header
189 lines.pop(0)
190
191 print("Hanging process info:")
192 print(" PID: %s" % pid)
193 for line in lines:
194 # wmic will output a bunch of empty strings, we ignore these
195 if line: print(" Command line: %s" % line)
196
197 if dump_stacks:
199
200
201def KillPosix(pid):
202 try:
203 os.kill(int(pid), signal.SIGKILL)
204 except:
205 # Ignore this, the process is already dead from killing another process.
206 pass
207
208
209def KillWindows(pid):
210 # os.kill is not available until python 2.7
211 cmd = "taskkill /F /PID %s" % pid
212 p = subprocess.Popen(cmd,
213 stdout=subprocess.PIPE,
214 stderr=subprocess.PIPE,
215 shell=True,
216 universal_newlines=True)
217 p.communicate()
218
219
220def Kill(name, dump_stacks=False):
221 if name not in EXECUTABLE_NAMES[os_name]:
222 return 0
223 print("***************** Killing %s *****************" % name)
224 platform_name = EXECUTABLE_NAMES[os_name][name]
225 pids = GetPids(platform_name)
226 for pid in pids:
227 PrintPidInfo(pid, dump_stacks)
228 if os_name == "win32":
229 KillWindows(pid)
230 else:
231 KillPosix(pid)
232 print("Killed pid: %s" % pid)
233 if len(pids) == 0:
234 print(" No %s processes found." % name)
235 return len(pids)
236
237
239 status = Kill('firefox')
240 # We don't give error on killing chrome. It happens quite often that the
241 # browser controller fails in killing chrome, so we silently do it here.
242 Kill('chrome')
243 status += Kill('chrome_helper')
244 status += Kill('iexplore')
245 status += Kill('safari')
246 return status
247
248
250 status = Kill('git')
251 return status
252
253
255 status = Kill('vctip')
256 status += Kill('mspdbsrv')
257 return status
258
259
261 status = Kill("dart", dump_stacks=True)
262 status += Kill("gen_snapshot", dump_stacks=True)
263 status += Kill("dartaotruntime", dump_stacks=True)
264 status += Kill("dart_precompiled_runtime", dump_stacks=True)
265 status += Kill("flutter_tester", dump_stacks=True)
266 return status
267
268
269def Main():
270 options = GetOptions()
271 status = 0
272 if options.kill_dart == 'True':
273 if os_name == "win32":
274 # TODO(24086): Add result of KillDart into status once pub hang is fixed.
275 KillDart()
276 else:
277 status += KillDart()
278 if options.kill_vc == 'True':
279 status += KillVCSystems()
280 if options.kill_vsbuild == 'True' and os_name == 'win32':
281 status += KillVSBuild()
282 if options.kill_browsers == 'True':
283 status += KillBrowsers()
284 return status
285
286
287if __name__ == '__main__':
288 sys.exit(Main())
def print(*args, **kwargs)
Definition: run_tests.py:49
def KillDart()
Definition: task_kill.py:260
def KillVCSystems()
Definition: task_kill.py:249
def GetPids(process_name)
Definition: task_kill.py:148
def KillPosix(pid)
Definition: task_kill.py:201
def GetOptions()
Definition: task_kill.py:73
def PrintPidInfo(pid, dump_stacks)
Definition: task_kill.py:176
def KillVSBuild()
Definition: task_kill.py:254
def GetPidsPosix(process_name)
Definition: task_kill.py:104
def KillBrowsers()
Definition: task_kill.py:238
def KillWindows(pid)
Definition: task_kill.py:209
def Kill(name, dump_stacks=False)
Definition: task_kill.py:220
def GetPidsWindows(process_name)
Definition: task_kill.py:128
def Main()
Definition: task_kill.py:269
def PrintPidStackInfo(pid)
Definition: task_kill.py:155
def GuessOS()
Definition: utils.py:21
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741