OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 5 # BSD-style license that can be found in the LICENSE file. |
6 # | 6 # |
7 | 7 |
8 # A script to kill hanging processs. The tool will return non-zero if any | 8 # A script to kill hanging processs. The tool will return non-zero if any |
9 # process was actually found. | 9 # process was actually found. |
10 # | 10 # |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 'fletch-vm': 'fletch-vm', | 56 'fletch-vm': 'fletch-vm', |
57 } | 57 } |
58 } | 58 } |
59 | 59 |
60 INFO_COMMAND = { | 60 INFO_COMMAND = { |
61 'win32': 'wmic process where Processid=%s get CommandLine', | 61 'win32': 'wmic process where Processid=%s get CommandLine', |
62 'macos': POSIX_INFO, | 62 'macos': POSIX_INFO, |
63 'linux': POSIX_INFO, | 63 'linux': POSIX_INFO, |
64 } | 64 } |
65 | 65 |
| 66 STACK_INFO_COMMAND = { |
| 67 'win32': None, |
| 68 'macos': '/usr/bin/sample %s 1 4000 -mayDie', |
| 69 'linux': '/usr/bin/eu-stack -p %s', |
| 70 } |
| 71 |
66 def GetOptions(): | 72 def GetOptions(): |
67 parser = optparse.OptionParser("usage: %prog [options]") | 73 parser = optparse.OptionParser("usage: %prog [options]") |
68 parser.add_option("--kill_dart", default=True, | 74 parser.add_option("--kill_dart", default=True, |
69 help="Kill all dart processes") | 75 help="Kill all dart processes") |
70 parser.add_option("--kill_fletch", default=True, | 76 parser.add_option("--kill_fletch", default=True, |
71 help="Kill all fletch and fletch-vm processes") | 77 help="Kill all fletch and fletch-vm processes") |
72 parser.add_option("--kill_vc", default=True, | 78 parser.add_option("--kill_vc", default=True, |
73 help="Kill all git and svn processes") | 79 help="Kill all git and svn processes") |
74 parser.add_option("--kill_browsers", default=False, | 80 parser.add_option("--kill_browsers", default=False, |
75 help="Kill all browser processes") | 81 help="Kill all browser processes") |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 if len(split) > 2 and split[0] == process_name: | 123 if len(split) > 2 and split[0] == process_name: |
118 results.append(split[1]) | 124 results.append(split[1]) |
119 return results | 125 return results |
120 | 126 |
121 def GetPids(process_name): | 127 def GetPids(process_name): |
122 if os_name == "win32": | 128 if os_name == "win32": |
123 return GetPidsWindows(process_name) | 129 return GetPidsWindows(process_name) |
124 else: | 130 else: |
125 return GetPidsPosix(process_name) | 131 return GetPidsPosix(process_name) |
126 | 132 |
127 def PrintPidInfo(pid): | 133 def PrintPidStackInfo(pid): |
| 134 command_pattern = STACK_INFO_COMMAND.get(os_name, False) |
| 135 if command_pattern: |
| 136 p = subprocess.Popen(command_pattern % pid, |
| 137 stdout=subprocess.PIPE, |
| 138 stderr=subprocess.PIPE, |
| 139 shell=True) |
| 140 stdout, stderr = p.communicate() |
| 141 stdout = stdout.splitlines() |
| 142 stderr = stderr.splitlines() |
| 143 |
| 144 print " Stack:" |
| 145 for line in stdout: |
| 146 print " %s" % line |
| 147 if stderr: |
| 148 print " Stack (stderr):" |
| 149 for line in stderr: |
| 150 print " %s" % line |
| 151 |
| 152 def PrintPidInfo(pid, dump_stacks): |
128 # We assume that the list command will return lines in the format: | 153 # We assume that the list command will return lines in the format: |
129 # EXECUTABLE_PATH ARGS | 154 # EXECUTABLE_PATH ARGS |
130 # There may be blank strings in the output | 155 # There may be blank strings in the output |
131 p = subprocess.Popen(INFO_COMMAND[os_name] % pid, | 156 p = subprocess.Popen(INFO_COMMAND[os_name] % pid, |
132 stdout=subprocess.PIPE, | 157 stdout=subprocess.PIPE, |
133 stderr=subprocess.PIPE, | 158 stderr=subprocess.PIPE, |
134 shell=True) | 159 shell=True) |
135 output, stderr = p.communicate() | 160 output, stderr = p.communicate() |
136 lines = output.splitlines() | 161 lines = output.splitlines() |
137 | 162 |
138 # Pop the header | 163 # Pop the header |
139 lines.pop(0) | 164 lines.pop(0) |
| 165 |
| 166 print "Hanging process info:" |
| 167 print " PID: %s" % pid |
140 for line in lines: | 168 for line in lines: |
141 # wmic will output a bunch of empty strings, we ignore these | 169 # wmic will output a bunch of empty strings, we ignore these |
142 if len(line) >= 1: | 170 if line: print " Command line: %s" % line |
143 print("Hanging process info:") | |
144 print(" PID: %s" % pid) | |
145 print(" Command line: %s" % line) | |
146 | 171 |
| 172 if dump_stacks: |
| 173 PrintPidStackInfo(pid) |
147 | 174 |
148 def KillPosix(pid): | 175 def KillPosix(pid): |
149 try: | 176 try: |
150 os.kill(int(pid), signal.SIGKILL) | 177 os.kill(int(pid), signal.SIGKILL) |
151 except: | 178 except: |
152 # Ignore this, the process is already dead from killing another process. | 179 # Ignore this, the process is already dead from killing another process. |
153 pass | 180 pass |
154 | 181 |
155 def KillWindows(pid): | 182 def KillWindows(pid): |
156 # os.kill is not available until python 2.7 | 183 # os.kill is not available until python 2.7 |
157 cmd = "taskkill /F /PID %s" % pid | 184 cmd = "taskkill /F /PID %s" % pid |
158 p = subprocess.Popen(cmd, | 185 p = subprocess.Popen(cmd, |
159 stdout=subprocess.PIPE, | 186 stdout=subprocess.PIPE, |
160 stderr=subprocess.PIPE, | 187 stderr=subprocess.PIPE, |
161 shell=True) | 188 shell=True) |
162 p.communicate() | 189 p.communicate() |
163 | 190 |
164 def Kill(name): | 191 def Kill(name, dump_stacks=False): |
165 if name not in EXECUTABLE_NAMES[os_name]: | 192 if name not in EXECUTABLE_NAMES[os_name]: |
166 return 0 | 193 return 0 |
167 print("***************** Killing %s *****************" % name) | 194 print("***************** Killing %s *****************" % name) |
168 platform_name = EXECUTABLE_NAMES[os_name][name] | 195 platform_name = EXECUTABLE_NAMES[os_name][name] |
169 pids = GetPids(platform_name) | 196 pids = GetPids(platform_name) |
170 for pid in pids: | 197 for pid in pids: |
171 PrintPidInfo(pid) | 198 PrintPidInfo(pid, dump_stacks) |
172 if os_name == "win32": | 199 if os_name == "win32": |
173 KillWindows(pid) | 200 KillWindows(pid) |
174 else: | 201 else: |
175 KillPosix(pid) | 202 KillPosix(pid) |
176 print("Killed pid: %s" % pid) | 203 print("Killed pid: %s" % pid) |
177 if len(pids) == 0: | 204 if len(pids) == 0: |
178 print(" No %s processes found." % name) | 205 print(" No %s processes found." % name) |
179 return len(pids) | 206 return len(pids) |
180 | 207 |
181 def KillBrowsers(): | 208 def KillBrowsers(): |
182 status = Kill('firefox') | 209 status = Kill('firefox') |
183 # We don't give error on killing chrome. It happens quite often that the | 210 # We don't give error on killing chrome. It happens quite often that the |
184 # browser controller fails in killing chrome, so we silently do it here. | 211 # browser controller fails in killing chrome, so we silently do it here. |
185 Kill('chrome') | 212 Kill('chrome') |
186 status += Kill('iexplore') | 213 status += Kill('iexplore') |
187 status += Kill('safari') | 214 status += Kill('safari') |
188 status += Kill('content_shell') | 215 status += Kill('content_shell') |
189 return status | 216 return status |
190 | 217 |
191 def KillVCSystems(): | 218 def KillVCSystems(): |
192 status = Kill('git') | 219 status = Kill('git') |
193 status += Kill('svn') | 220 status += Kill('svn') |
194 return status | 221 return status |
195 | 222 |
196 def KillDart(): | 223 def KillDart(): |
197 status = Kill("dart") | 224 status = Kill("dart", dump_stacks=True) |
198 return status | 225 return status |
199 | 226 |
200 def KillFletch(): | 227 def KillFletch(): |
201 status = Kill("fletch") | 228 status = Kill("fletch") |
202 status += Kill("fletch-vm") | 229 status += Kill("fletch-vm") |
203 return status | 230 return status |
204 | 231 |
205 def Main(): | 232 def Main(): |
206 options = GetOptions() | 233 options = GetOptions() |
207 status = 0 | 234 status = 0 |
208 if options.kill_dart: | 235 if options.kill_dart: |
209 if os_name == "win32": | 236 if os_name == "win32": |
210 # TODO(24086): Add result of KillDart into status once pub hang is fixed. | 237 # TODO(24086): Add result of KillDart into status once pub hang is fixed. |
211 KillDart() | 238 KillDart() |
212 else: | 239 else: |
213 status += KillDart() | 240 status += KillDart() |
214 if options.kill_fletch: | 241 if options.kill_fletch: |
215 status += KillFletch() | 242 status += KillFletch() |
216 if options.kill_vc: | 243 if options.kill_vc: |
217 status += KillVCSystems() | 244 status += KillVCSystems() |
218 if options.kill_browsers: | 245 if options.kill_browsers: |
219 status += KillBrowsers() | 246 status += KillBrowsers() |
220 return status | 247 return status |
221 | 248 |
222 if __name__ == '__main__': | 249 if __name__ == '__main__': |
223 sys.exit(Main()) | 250 sys.exit(Main()) |
OLD | NEW |