OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 from skypy.skyserver import SkyServer | 6 from skypy.skyserver import SkyServer |
7 import argparse | 7 import argparse |
8 import json | 8 import json |
9 import logging | 9 import logging |
10 import os | 10 import os |
11 import pipes | 11 import pipes |
12 import requests | 12 import requests |
13 import signal | 13 import signal |
14 import skypy.paths | 14 import skypy.paths |
15 import StringIO | 15 import StringIO |
16 import subprocess | 16 import subprocess |
17 import sys | 17 import sys |
18 import time | 18 import time |
19 import urlparse | 19 import urlparse |
20 import re | |
20 | 21 |
21 SRC_ROOT = skypy.paths.Paths('ignored').src_root | 22 SRC_ROOT = skypy.paths.Paths('ignored').src_root |
22 sys.path.insert(0, os.path.join(SRC_ROOT, 'build', 'android')) | 23 sys.path.insert(0, os.path.join(SRC_ROOT, 'build', 'android')) |
23 from pylib import android_commands | 24 from pylib import android_commands |
24 from pylib import constants | 25 from pylib import constants |
25 from pylib import forwarder | 26 from pylib import forwarder |
26 | 27 |
27 | 28 |
28 SUPPORTED_MIME_TYPES = [ | 29 SUPPORTED_MIME_TYPES = [ |
29 'text/html', | 30 'text/html', |
30 'text/sky', | 31 'text/sky', |
31 'text/plain', | 32 'text/plain', |
32 ] | 33 ] |
33 | 34 |
34 DEFAULT_SKY_COMMAND_PORT = 7777 | 35 DEFAULT_SKY_COMMAND_PORT = 7777 |
35 GDB_PORT = 8888 | 36 GDB_PORT = 8888 |
36 SKY_SERVER_PORT = 9999 | 37 SKY_SERVER_PORT = 9999 |
37 PID_FILE_PATH = "/tmp/skydb.pids" | 38 PID_FILE_PATH = "/tmp/skydb.pids" |
38 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example s/home.sky" | 39 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example s/home.sky" |
39 | 40 |
40 ANDROID_PACKAGE = "org.chromium.mojo.shell" | 41 ANDROID_PACKAGE = "org.chromium.mojo.shell" |
41 ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE | 42 ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE |
42 | 43 |
44 | |
43 # FIXME: Move this into mopy.config | 45 # FIXME: Move this into mopy.config |
44 def gn_args_from_build_dir(build_dir): | 46 def gn_args_from_build_dir(build_dir): |
45 gn_cmd = [ | 47 gn_cmd = [ |
46 'gn', 'args', | 48 'gn', 'args', |
47 build_dir, | 49 build_dir, |
48 '--list', '--short' | 50 '--list', '--short' |
49 ] | 51 ] |
50 config = {} | 52 config = {} |
51 for line in subprocess.check_output(gn_cmd).strip().split('\n'): | 53 for line in subprocess.check_output(gn_cmd).strip().split('\n'): |
52 # FIXME: This doesn't handle = in values. | 54 # FIXME: This doesn't handle = in values. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
90 'am', 'start', | 92 'am', 'start', |
91 '-W', | 93 '-W', |
92 '-S', | 94 '-S', |
93 '-a', 'android.intent.action.VIEW', | 95 '-a', 'android.intent.action.VIEW', |
94 '-n', ANDROID_ACTIVITY, | 96 '-n', ANDROID_ACTIVITY, |
95 # FIXME: This quoting is very error-prone. Perhaps we should read | 97 # FIXME: This quoting is very error-prone. Perhaps we should read |
96 # our args from a file instead? | 98 # our args from a file instead? |
97 '--esa', 'parameters', ','.join(escaped_args), | 99 '--esa', 'parameters', ','.join(escaped_args), |
98 ] | 100 ] |
99 | 101 |
100 def _build_mojo_shell_command(self, args): | 102 def _build_mojo_shell_command(self, args, is_android): |
101 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') | 103 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') |
102 for mime_type in SUPPORTED_MIME_TYPES] | 104 for mime_type in SUPPORTED_MIME_TYPES] |
103 | 105 |
104 remote_command_port = self.pids.get('remote_sky_command_port', self.pids ['sky_command_port']) | 106 remote_command_port = self.pids.get('remote_sky_command_port', self.pids ['sky_command_port']) |
105 | 107 |
106 shell_args = [ | 108 shell_args = [ |
107 '--v=1', | 109 '--v=1', |
108 '--content-handlers=%s' % ','.join(content_handlers), | 110 '--content-handlers=%s' % ','.join(content_handlers), |
109 '--url-mappings=mojo:window_manager=mojo:sky_debugger', | 111 '--url-mappings=mojo:window_manager=mojo:sky_debugger', |
110 '--args-for=mojo:sky_debugger_prompt %d' % remote_command_port, | 112 '--args-for=mojo:sky_debugger_prompt %d' % remote_command_port, |
111 'mojo:window_manager', | 113 'mojo:window_manager', |
112 ] | 114 ] |
113 | 115 |
116 # Desktop-only work-around for mojo crashing under chromoting. | |
117 if not is_android and args.use_osmesa: | |
118 shell_args.append( | |
119 '--args-for=mojo:native_viewport_service --use-osmesa') | |
120 | |
121 if is_android and args.gdb: | |
122 shell_args.append('--wait_for_debugger') | |
123 | |
114 if 'remote_sky_server_port' in self.pids: | 124 if 'remote_sky_server_port' in self.pids: |
115 shell_command = self._wrap_for_android(shell_args) | 125 shell_command = self._wrap_for_android(shell_args) |
116 else: | 126 else: |
117 shell_command = [self.paths.mojo_shell_path] + shell_args | 127 shell_command = [self.paths.mojo_shell_path] + shell_args |
118 | 128 |
119 return shell_command | 129 return shell_command |
120 | 130 |
121 def _connect_to_device(self): | 131 def _connect_to_device(self): |
122 device = android_commands.AndroidCommands( | 132 device = android_commands.AndroidCommands( |
123 android_commands.GetAttachedDevices()[0]) | 133 android_commands.GetAttachedDevices()[0]) |
124 device.EnableAdbRoot() | 134 device.EnableAdbRoot() |
125 return device | 135 return device |
126 | 136 |
127 def sky_server_for_args(self, args): | 137 def sky_server_for_args(self, args): |
128 # FIXME: This is a hack. sky_server should just take a build_dir | 138 # FIXME: This is a hack. sky_server should just take a build_dir |
129 # not a magical "configuration" name. | 139 # not a magical "configuration" name. |
130 configuration = os.path.basename(os.path.normpath(args.build_dir)) | 140 configuration = os.path.basename(os.path.normpath(args.build_dir)) |
131 server_root = self._server_root_for_url(args.url_or_path) | 141 server_root = self._server_root_for_url(args.url_or_path) |
132 sky_server = SkyServer(self.paths, SKY_SERVER_PORT, | 142 sky_server = SkyServer(self.paths, SKY_SERVER_PORT, |
133 configuration, server_root) | 143 configuration, server_root) |
134 return sky_server | 144 return sky_server |
135 | 145 |
136 def _create_paths_for_build_dir(self, build_dir): | 146 def _create_paths_for_build_dir(self, build_dir): |
137 # skypy.paths.Paths takes a root-relative build_dir argument. :( | 147 # skypy.paths.Paths takes a root-relative build_dir argument. :( |
138 abs_build_dir = os.path.abspath(build_dir) | 148 abs_build_dir = os.path.abspath(build_dir) |
139 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT) | 149 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT) |
140 return skypy.paths.Paths(root_relative_build_dir) | 150 return skypy.paths.Paths(root_relative_build_dir) |
141 | 151 |
152 def _find_remote_pid_for_package(self, package): | |
153 ps_output = subprocess.check_output(['adb', 'shell', 'ps']) | |
154 for line in ps_output.split('\n'): | |
155 fields = line.split() | |
156 if fields and 'org' in fields[-1]: | |
157 print fields[-1] | |
qsr
2015/01/16 00:04:19
Is that some debugging leftover?
eseidel
2015/01/16 00:14:06
Yes! Removed.
| |
158 if fields and fields[-1] == package: | |
159 return fields[1] | |
160 return None | |
161 | |
162 def _find_install_location_for_package(self, package): | |
163 pm_command = ['adb', 'shell', 'pm', 'path', package] | |
164 pm_output = subprocess.check_output(pm_command) | |
165 # e.g. package:/data/app/org.chromium.mojo.shell-1/base.apk | |
166 return pm_output.split(':')[-1] | |
167 | |
142 def start_command(self, args): | 168 def start_command(self, args): |
143 # FIXME: Lame that we use self for a command-specific variable. | 169 # FIXME: Lame that we use self for a command-specific variable. |
144 self.paths = self._create_paths_for_build_dir(args.build_dir) | 170 self.paths = self._create_paths_for_build_dir(args.build_dir) |
145 self.stop_command(None) # Quit any existing process. | 171 self.stop_command(None) # Quit any existing process. |
146 self.pids = {} # Clear out our pid file. | 172 self.pids = {} # Clear out our pid file. |
147 | 173 |
148 if not os.path.exists(self.paths.mojo_shell_path): | 174 if not os.path.exists(self.paths.mojo_shell_path): |
149 print "mojo_shell not found in build_dir '%s'" % args.build_dir | 175 print "mojo_shell not found in build_dir '%s'" % args.build_dir |
150 print "Are you sure you sure that's a valid build_dir location?" | 176 print "Are you sure you sure that's a valid build_dir location?" |
151 print "See skydb start --help for more info" | 177 print "See skydb start --help for more info" |
(...skipping 23 matching lines...) Expand all Loading... | |
175 device_http_port = forwarder.Forwarder.DevicePortForHostPort( | 201 device_http_port = forwarder.Forwarder.DevicePortForHostPort( |
176 sky_server.port) | 202 sky_server.port) |
177 self.pids['remote_sky_server_port'] = device_http_port | 203 self.pids['remote_sky_server_port'] = device_http_port |
178 | 204 |
179 port_string = 'tcp:%s' % args.command_port | 205 port_string = 'tcp:%s' % args.command_port |
180 subprocess.check_call([ | 206 subprocess.check_call([ |
181 'adb', 'forward', port_string, port_string | 207 'adb', 'forward', port_string, port_string |
182 ]) | 208 ]) |
183 self.pids['remote_sky_command_port'] = args.command_port | 209 self.pids['remote_sky_command_port'] = args.command_port |
184 | 210 |
185 shell_command = self._build_mojo_shell_command(args) | 211 shell_command = self._build_mojo_shell_command(args, is_android) |
186 | 212 |
187 if not is_android: | 213 # On android we can't launch inside gdb, but rather have to attach. |
188 # Desktop-only work-around for mojo crashing under chromoting. | 214 if not is_android and args.gdb: |
189 if args.use_osmesa: | 215 shell_command = ['gdbserver', ':%s' % GDB_PORT] + shell_command |
qsr
2015/01/16 00:04:19
%d? Here and everywhere you format an integer
eseidel
2015/01/16 00:14:06
OK. What's the benefit?
qsr
2015/01/16 00:46:40
It will crash if this is not a number. Not much, b
| |
190 shell_args.append( | |
191 '--args-for=mojo:native_viewport_service --use-osmesa') | |
192 | |
193 # On android we can't launch inside gdb, but rather have to attach. | |
194 if args.gdb: | |
195 shell_command = ['gdbserver', ':%s' % GDB_PORT] + shell_command | |
196 | 216 |
197 print ' '.join(map(pipes.quote, shell_command)) | 217 print ' '.join(map(pipes.quote, shell_command)) |
198 self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid | 218 # This pid is meaningless on android (it's the adb shell pid) |
219 start_command_pid = subprocess.Popen(shell_command).pid | |
220 | |
221 if is_android: | |
222 # TODO(eseidel): am start -W does not seem to work? | |
223 pid_tries = 0 | |
224 while True: | |
225 pid = self._find_remote_pid_for_package(ANDROID_PACKAGE) | |
226 if pid or pid_tries > 3: | |
227 break | |
228 logging.warn('No pid for %s yet, waiting' % ANDROID_PACKAGE) | |
229 time.sleep(5) | |
230 pid_tries += 1 | |
231 | |
232 self.pids['mojo_shell_pid'] = pid | |
233 if not self.pids['mojo_shell_pid']: | |
qsr
2015/01/16 00:04:18
Any reason not to write this:
if not pid:
...
eseidel
2015/01/16 00:14:06
Done.
| |
234 logging.error('Failed to find mojo_shell pid on device!') | |
235 return | |
236 else: | |
237 self.pids['mojo_shell_pid'] = start_command_pid | |
199 | 238 |
200 if args.gdb and is_android: | 239 if args.gdb and is_android: |
201 gdbserver_cmd = ['gdbserver', '--attach', ':%s' % GDB_PORT] | 240 # We push our own copy of gdbserver with the package since |
202 self.pids['remote_gdbserver_pid'] = subprocess.Popen(shell_command). pid | 241 # the default gdbserver is a different version from our gdb. |
242 package_path = \ | |
243 self._find_install_location_for_package(ANDROID_PACKAGE) | |
244 gdb_server_path = os.path.join( | |
245 os.path.dirname(package_path), 'lib/arm/gdbserver') | |
246 gdbserver_cmd = [ | |
247 'adb', 'shell', | |
248 gdb_server_path, '--attach', | |
249 ':%s' % GDB_PORT, | |
250 str(self.pids['mojo_shell_pid']) | |
251 ] | |
252 print ' '.join(map(pipes.quote, gdbserver_cmd)) | |
253 self.pids['adb_shell_gdbserver_pid'] = \ | |
254 subprocess.Popen(gdbserver_cmd).pid | |
qsr
2015/01/16 00:04:19
I am missing something here. Why are you transform
eseidel
2015/01/16 00:14:06
I'm only transforming it into a string for the pri
qsr
2015/01/16 00:46:40
That's what I was missing. Sorry.
| |
203 | 255 |
204 port_string = 'tcp:%s' % GDB_PORT | 256 port_string = 'tcp:%s' % GDB_PORT |
205 subprocess.check_call([ | 257 subprocess.check_call([ |
206 'adb', 'forward', port_string, port_string | 258 'adb', 'forward', port_string, port_string |
207 ]) | 259 ]) |
208 self.pids['remote_gdbserver_port'] = GDB_PORT | 260 self.pids['remote_gdbserver_port'] = GDB_PORT |
209 | 261 |
210 if not args.gdb: | 262 if not args.gdb: |
211 if not self._wait_for_sky_command_port(): | 263 if not self._wait_for_sky_command_port(): |
212 logging.error('Failed to start sky') | 264 logging.error('Failed to start sky') |
(...skipping 10 matching lines...) Expand all Loading... | |
223 return | 275 return |
224 logging.info('Killing %s (%s).' % (name, pid)) | 276 logging.info('Killing %s (%s).' % (name, pid)) |
225 try: | 277 try: |
226 os.kill(pid, signal.SIGTERM) | 278 os.kill(pid, signal.SIGTERM) |
227 except OSError: | 279 except OSError: |
228 logging.info('%s (%s) already gone.' % (name, pid)) | 280 logging.info('%s (%s) already gone.' % (name, pid)) |
229 | 281 |
230 def stop_command(self, args): | 282 def stop_command(self, args): |
231 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. | 283 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. |
232 # self._send_command_to_sky('/quit') | 284 # self._send_command_to_sky('/quit') |
233 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') | |
234 | 285 |
235 self._kill_if_exists('sky_server_pid', 'sky_server') | 286 self._kill_if_exists('sky_server_pid', 'sky_server') |
287 | |
236 # We could be much more surgical here: | 288 # We could be much more surgical here: |
237 if 'remote_sky_server_port' in self.pids: | 289 if 'remote_sky_server_port' in self.pids: |
238 device = android_commands.AndroidCommands( | 290 device = android_commands.AndroidCommands( |
239 self.pids['device_serial']) | 291 self.pids['device_serial']) |
240 forwarder.Forwarder.UnmapAllDevicePorts(device) | 292 forwarder.Forwarder.UnmapAllDevicePorts(device) |
241 | 293 |
242 if 'remote_sky_command_port' in self.pids: | 294 if 'remote_sky_command_port' in self.pids: |
243 # adb forward --remove takes the *host* port, not the remote port. | 295 # adb forward --remove takes the *host* port, not the remote port. |
244 port_string = 'tcp:%s' % self.pids['sky_command_port'] | 296 port_string = 'tcp:%s' % self.pids['sky_command_port'] |
245 subprocess.call(['adb', 'forward', '--remove', port_string]) | 297 subprocess.call(['adb', 'forward', '--remove', port_string]) |
246 | 298 |
247 subprocess.call([ | 299 subprocess.call([ |
248 'adb', 'shell', 'am', 'force-stop', ANDROID_PACKAGE]) | 300 'adb', 'shell', 'am', 'force-stop', ANDROID_PACKAGE]) |
301 else: | |
302 # Only try to kill mojo_shell if it's running locally. | |
303 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') | |
249 | 304 |
250 if 'remote_gdbserver_port' in self.pids: | 305 if 'remote_gdbserver_port' in self.pids: |
306 self._kill_if_exists('adb_shell_gdbserver_pid', 'adb shell gdbserver ') | |
307 | |
251 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port'] | 308 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port'] |
252 subprocess.call(['adb', 'forward', '--remove', port_string]) | 309 subprocess.call(['adb', 'forward', '--remove', port_string]) |
253 | 310 |
311 self._kill_if_exists('mojo_cache_linker_pid', 'mojo cache linker') | |
312 | |
254 def load_command(self, args): | 313 def load_command(self, args): |
255 if not urlparse.urlparse(args.url_or_path).scheme: | 314 if not urlparse.urlparse(args.url_or_path).scheme: |
256 # The load happens on the remote device, use the remote port. | 315 # The load happens on the remote device, use the remote port. |
257 remote_sky_server_port = self.pids.get('remote_sky_server_port', | 316 remote_sky_server_port = self.pids.get('remote_sky_server_port', |
258 self.pids['sky_server_port']) | 317 self.pids['sky_server_port']) |
259 url = SkyServer.url_for_path(remote_sky_server_port, | 318 url = SkyServer.url_for_path(remote_sky_server_port, |
260 self.pids['sky_server_root'], args.url_or_path) | 319 self.pids['sky_server_root'], args.url_or_path) |
261 else: | 320 else: |
262 url = args.url_or_path | 321 url = args.url_or_path |
263 self._send_command_to_sky('/load', url) | 322 self._send_command_to_sky('/load', url) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 'AndroidHandler', | 375 'AndroidHandler', |
317 'MojoMain', | 376 'MojoMain', |
318 'MojoShellActivity', | 377 'MojoShellActivity', |
319 'MojoShellApplication', | 378 'MojoShellApplication', |
320 'chromium', | 379 'chromium', |
321 ] | 380 ] |
322 subprocess.call(['adb', 'logcat', '-d', '-s'] + TAGS) | 381 subprocess.call(['adb', 'logcat', '-d', '-s'] + TAGS) |
323 | 382 |
324 def gdb_attach_command(self, args): | 383 def gdb_attach_command(self, args): |
325 self.paths = self._create_paths_for_build_dir(self.pids['build_dir']) | 384 self.paths = self._create_paths_for_build_dir(self.pids['build_dir']) |
385 | |
386 self._kill_if_exists('mojo_cache_linker_pid', 'mojo cache linker') | |
387 | |
388 links_path = '/tmp/mojo_cache_links' | |
389 if not os.path.exists(links_path): | |
390 os.makedirs(links_path) | |
qsr
2015/01/16 00:04:18
You do not seem to ever be cleaning this directory
eseidel
2015/01/16 00:14:06
Unclear. I could? Originally I had the new scrip
qsr
2015/01/16 00:46:40
I fear this will quickly be full on unused files.
| |
391 shell_link_path = os.path.join(links_path, 'libmojo_shell.so') | |
392 if os.path.lexists(shell_link_path): | |
393 os.unlink(shell_link_path) | |
394 os.symlink(self.paths.mojo_shell_path, shell_link_path) | |
395 | |
396 logcat_cmd = ['adb', 'logcat'] | |
397 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE) | |
398 | |
399 mojo_cache_linker_path = os.path.join( | |
400 self.paths.sky_tools_directory, 'mojo_cache_linker.py') | |
401 cache_linker_cmd = [ | |
402 mojo_cache_linker_path, | |
403 links_path, | |
404 self.pids['build_dir'], | |
405 'http://localhost:%s' % self.pids['remote_sky_server_port'] | |
406 ] | |
407 self.pids['mojo_cache_linker_pid'] = \ | |
408 subprocess.Popen(cache_linker_cmd, stdin=logcat.stdout).pid | |
409 | |
410 # TODO(eseidel): Need to sync down system libraries into a directory. | |
411 # For example, this is what adb_gdb uses: | |
412 # set print pretty 1 | |
413 # python | |
414 # import sys | |
415 # sys.path.insert(0, '/src/mojo/src/tools/gdb/') | |
416 # try: | |
417 # import gdb_chrome | |
418 # finally: | |
419 # sys.path.pop(0) | |
420 # end | |
421 # file /tmp/eseidel-adb-gdb-tmp-19640/app_process | |
422 # directory /src/mojo/src | |
423 # set solib-absolute-prefix /tmp/eseidel-adb-gdb-libs | |
424 # set solib-search-path /tmp/eseidel-adb-gdb-libs/system:/tmp/eseidel-ad b-gdb-libs/system/vendor:/tmp/eseidel-adb-gdb-libs/system/vendor/lib:/tmp/eseide l-adb-gdb-libs/system/vendor/lib/egl:/tmp/eseidel-adb-gdb-libs/system/bin:/tmp/e seidel-adb-gdb-libs/system/lib:/tmp/eseidel-adb-gdb-libs/system/lib/hw::/tmp/ese idel-adb-gdb-libs:/src/mojo/src/foo/Debug/lib | |
425 # echo Attaching and reading symbols, this may take a while.. | |
426 # target remote :5039 | |
427 | |
428 symbol_search_paths = [ | |
429 links_path, | |
430 self.pids['build_dir'], | |
431 ] | |
432 gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk/toolcha ins/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gd b') | |
qsr
2015/01/16 00:04:19
This should be 80 chars long... You also might wan
eseidel
2015/01/16 00:14:06
Eek! I need to fix this lookup before landing. Th
| |
326 gdb_command = [ | 433 gdb_command = [ |
327 '/usr/bin/gdb', self.paths.mojo_shell_path, | 434 gdb_path, |
328 '--eval-command', 'target remote localhost:%s' % GDB_PORT | 435 '--eval-command', 'file %s' % self.paths.mojo_shell_path, |
436 '--eval-command', 'directory %s' % self.paths.src_root, | |
437 '--eval-command', 'target remote localhost:%s' % GDB_PORT, | |
438 '--eval-command', 'set solib-search-path %s' % | |
439 ':'.join(symbol_search_paths), | |
329 ] | 440 ] |
330 print " ".join(gdb_command) | 441 print " ".join(gdb_command) |
331 # We don't want python listenting for signals or anything, so exec | 442 # We don't want python listenting for signals or anything, so exec |
332 # gdb and let it take the entire process. | 443 # gdb and let it take the entire process. |
333 os.execv(gdb_command[0], gdb_command) | 444 os.execv(gdb_command[0], gdb_command) |
334 | 445 |
335 def print_crash_command(self, args): | 446 def print_crash_command(self, args): |
336 logcat_cmd = ['adb', 'logcat', '-d'] | 447 logcat_cmd = ['adb', 'logcat', '-d'] |
337 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE) | 448 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE) |
338 | 449 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 load_parser.set_defaults(func=self.load_command) | 505 load_parser.set_defaults(func=self.load_command) |
395 | 506 |
396 args = parser.parse_args() | 507 args = parser.parse_args() |
397 args.func(args) | 508 args.func(args) |
398 | 509 |
399 self._write_pid_file(PID_FILE_PATH, self.pids) | 510 self._write_pid_file(PID_FILE_PATH, self.pids) |
400 | 511 |
401 | 512 |
402 if __name__ == '__main__': | 513 if __name__ == '__main__': |
403 SkyDebugger().main() | 514 SkyDebugger().main() |
OLD | NEW |