Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: sky/tools/skydb

Issue 808053006: Make --gdb work again by using gdbserver (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import skypy.paths 6 import skypy.paths
7 from skypy.skyserver import SkyServer 7 from skypy.skyserver import SkyServer
8 import argparse 8 import argparse
9 import json 9 import json
10 import logging 10 import logging
(...skipping 13 matching lines...) Expand all
24 from pylib import forwarder 24 from pylib import forwarder
25 25
26 26
27 SUPPORTED_MIME_TYPES = [ 27 SUPPORTED_MIME_TYPES = [
28 'text/html', 28 'text/html',
29 'text/sky', 29 'text/sky',
30 'text/plain', 30 'text/plain',
31 ] 31 ]
32 32
33 DEFAULT_SKY_COMMAND_PORT = 7777 33 DEFAULT_SKY_COMMAND_PORT = 7777
34 GDB_PORT = 8888
34 SKY_SERVER_PORT = 9999 35 SKY_SERVER_PORT = 9999
35 PID_FILE_PATH = "/tmp/skydb.pids" 36 PID_FILE_PATH = "/tmp/skydb.pids"
36 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example s/home.sky" 37 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example s/home.sky"
37 38
38 39
39 # FIXME: Move this into mopy.config 40 # FIXME: Move this into mopy.config
40 def gn_args_from_build_dir(build_dir): 41 def gn_args_from_build_dir(build_dir):
41 gn_cmd = [ 42 gn_cmd = [
42 'gn', 'args', 43 'gn', 'args',
43 build_dir, 44 build_dir,
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 126
126 def sky_server_for_args(self, args): 127 def sky_server_for_args(self, args):
127 # FIXME: This is a hack. sky_server should just take a build_dir 128 # FIXME: This is a hack. sky_server should just take a build_dir
128 # not a magical "configuration" name. 129 # not a magical "configuration" name.
129 configuration = os.path.basename(os.path.normpath(args.build_dir)) 130 configuration = os.path.basename(os.path.normpath(args.build_dir))
130 server_root = self._server_root_for_url(args.url_or_path) 131 server_root = self._server_root_for_url(args.url_or_path)
131 sky_server = SkyServer(self.paths, SKY_SERVER_PORT, 132 sky_server = SkyServer(self.paths, SKY_SERVER_PORT,
132 configuration, server_root) 133 configuration, server_root)
133 return sky_server 134 return sky_server
134 135
136 def _create_paths_for_build_dir(self, build_dir):
137 # skypy.paths.Paths takes a root-relative build_dir argument. :(
138 abs_build_dir = os.path.abspath(build_dir)
139 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT)
140 return skypy.paths.Paths(root_relative_build_dir)
141
135 def start_command(self, args): 142 def start_command(self, args):
136 # skypy.paths.Paths takes a root-relative build_dir argument. :(
137 build_dir = os.path.abspath(args.build_dir)
138 root_relative_build_dir = os.path.relpath(build_dir, SRC_ROOT)
139 # FIXME: Lame that we use self for a command-specific variable. 143 # FIXME: Lame that we use self for a command-specific variable.
140 self.paths = skypy.paths.Paths(root_relative_build_dir) 144 self.paths = self._create_paths_for_build_dir(args.build_dir)
141 145
142 self.stop_command(None) # Quit any existing process. 146 self.stop_command(None) # Quit any existing process.
143 self.pids = {} # Clear out our pid file. 147 self.pids = {} # Clear out our pid file.
144 148
145 # FIXME: This is probably not the right way to compute is_android 149 # FIXME: This is probably not the right way to compute is_android
146 # from the build directory? 150 # from the build directory?
147 gn_args = gn_args_from_build_dir(args.build_dir) 151 gn_args = gn_args_from_build_dir(args.build_dir)
148 is_android = 'android_sdk_version' in gn_args 152 is_android = 'android_sdk_version' in gn_args
149 153
150 sky_server = self.sky_server_for_args(args) 154 sky_server = self.sky_server_for_args(args)
(...skipping 16 matching lines...) Expand all
167 sky_server.port) 171 sky_server.port)
168 self.pids['remote_sky_server_port'] = device_http_port 172 self.pids['remote_sky_server_port'] = device_http_port
169 173
170 port_string = 'tcp:%s' % args.command_port 174 port_string = 'tcp:%s' % args.command_port
171 subprocess.check_call([ 175 subprocess.check_call([
172 'adb', 'forward', port_string, port_string 176 'adb', 'forward', port_string, port_string
173 ]) 177 ])
174 self.pids['remote_sky_command_port'] = args.command_port 178 self.pids['remote_sky_command_port'] = args.command_port
175 179
176 shell_command = self._build_mojo_shell_command(args) 180 shell_command = self._build_mojo_shell_command(args)
181
182 # On android we can't launch inside gdb, but rather have to attach.
183 if args.gdb and not is_android:
184 shell_command = ['gdbserver', ':%s' % GDB_PORT] + shell_command
185
177 print ' '.join(map(pipes.quote, shell_command)) 186 print ' '.join(map(pipes.quote, shell_command))
178 self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid 187 self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid
179 188
180 if args.gdb: 189 if args.gdb and is_android:
181 print "Sorry, I'm not sure how best to wire up --gdb to work" 190 gdbserver_cmd = ['gdbserver', '--attach', ':%s' % GDB_PORT]
182 print "with mojo_shell as a background process. For now use:" 191 self.pids['remote_gdbserver_pid'] = subprocess.Popen(shell_command). pid
183 print "gdb --pid %s" % self.pids['mojo_shell_pid']
184 shell_command = ['gdb'] + shell_command
185 192
186 if not self._wait_for_sky_command_port(): 193 port_string = 'tcp:%s' % GDB_PORT
187 logging.error('Failed to start sky') 194 subprocess.check_call([
188 self.stop_command(None) 195 'adb', 'forward', port_string, port_string
196 ])
197 self.pids['remote_gdbserver_port'] = GDB_PORT
198
199 if not args.gdb:
200 if not self._wait_for_sky_command_port():
201 logging.error('Failed to start sky')
202 self.stop_command(None)
203 else:
204 self.load_command(args)
189 else: 205 else:
190 self.load_command(args) 206 print 'No load issued, connect with gdb first and then run load.'
191 207
192 def _kill_if_exists(self, key, name): 208 def _kill_if_exists(self, key, name):
193 pid = self.pids.pop(key, None) 209 pid = self.pids.pop(key, None)
194 if not pid: 210 if not pid:
195 logging.info('No pid for %s, nothing to do.' % name) 211 logging.info('No pid for %s, nothing to do.' % name)
196 return 212 return
197 logging.info('Killing %s (%s).' % (name, pid)) 213 logging.info('Killing %s (%s).' % (name, pid))
198 try: 214 try:
199 os.kill(pid, signal.SIGTERM) 215 os.kill(pid, signal.SIGTERM)
200 except OSError: 216 except OSError:
201 logging.info('%s (%s) already gone.' % (name, pid)) 217 logging.info('%s (%s) already gone.' % (name, pid))
202 218
203 def stop_command(self, args): 219 def stop_command(self, args):
204 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. 220 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown.
205 # self._send_command_to_sky('/quit') 221 # self._send_command_to_sky('/quit')
206 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') 222 self._kill_if_exists('mojo_shell_pid', 'mojo_shell')
207 223
208 self._kill_if_exists('sky_server_pid', 'sky_server') 224 self._kill_if_exists('sky_server_pid', 'sky_server')
209 # We could be much more surgical here: 225 # We could be much more surgical here:
210 if 'remote_sky_command_port' in self.pids: 226 if 'remote_sky_server_port' in self.pids:
eseidel 2015/01/13 20:11:32 This was just checking for the wrong key. They bo
211 device = android_commands.AndroidCommands( 227 device = android_commands.AndroidCommands(
212 self.pids['device_serial']) 228 self.pids['device_serial'])
213 forwarder.Forwarder.UnmapAllDevicePorts(device) 229 forwarder.Forwarder.UnmapAllDevicePorts(device)
214 230
215 if 'remote_sky_command_port' in self.pids: 231 if 'remote_sky_command_port' in self.pids:
216 # adb forward --remove takes the *host* port, not the remote port. 232 # adb forward --remove takes the *host* port, not the remote port.
217 port_string = 'tcp:%s' % self.pids['sky_command_port'] 233 port_string = 'tcp:%s' % self.pids['sky_command_port']
218 subprocess.call(['adb', 'forward', '--remove', port_string]) 234 subprocess.call(['adb', 'forward', '--remove', port_string])
219 235
236 if 'remote_gdbserver_port' in self.pids:
237 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port']
238 subprocess.call(['adb', 'forward', '--remove', port_string])
239
220 def load_command(self, args): 240 def load_command(self, args):
221 if not urlparse.urlparse(args.url_or_path).scheme: 241 if not urlparse.urlparse(args.url_or_path).scheme:
222 # The load happens on the remote device, use the remote port. 242 # The load happens on the remote device, use the remote port.
223 remote_sky_server_port = self.pids.get('remote_sky_server_port', 243 remote_sky_server_port = self.pids.get('remote_sky_server_port',
224 self.pids['sky_server_port']) 244 self.pids['sky_server_port'])
225 url = SkyServer.url_for_path(remote_sky_server_port, 245 url = SkyServer.url_for_path(remote_sky_server_port,
226 self.pids['sky_server_root'], args.url_or_path) 246 self.pids['sky_server_root'], args.url_or_path)
227 else: 247 else:
228 url = args.url_or_path 248 url = args.url_or_path
229 self._send_command_to_sky('/load', url) 249 self._send_command_to_sky('/load', url)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 def logcat_command(self, args): 300 def logcat_command(self, args):
281 TAGS = [ 301 TAGS = [
282 'AndroidHandler', 302 'AndroidHandler',
283 'MojoMain', 303 'MojoMain',
284 'MojoShellActivity', 304 'MojoShellActivity',
285 'MojoShellApplication', 305 'MojoShellApplication',
286 'chromium', 306 'chromium',
287 ] 307 ]
288 subprocess.call(['adb', 'logcat', '-s'] + TAGS) 308 subprocess.call(['adb', 'logcat', '-s'] + TAGS)
289 309
310 def gdb_attach_command(self, args):
311 self.paths = self._create_paths_for_build_dir(self.pids['build_dir'])
312 gdb_command = [
313 '/usr/bin/gdb', self.paths.mojo_shell_path,
314 '--eval-command', 'target remote localhost:%s' % GDB_PORT
315 ]
316 print " ".join(gdb_command)
317 # We don't want python listenting for signals or anything, so exec
318 # gdb and let it take the entire process.
319 os.execv(gdb_command[0], gdb_command)
320
290 def main(self): 321 def main(self):
291 logging.basicConfig(level=logging.INFO) 322 logging.basicConfig(level=logging.INFO)
292 logging.getLogger("requests").setLevel(logging.WARNING) 323 logging.getLogger("requests").setLevel(logging.WARNING)
293 324
294 self.pids = self._load_pid_file(PID_FILE_PATH) 325 self.pids = self._load_pid_file(PID_FILE_PATH)
295 326
296 parser = argparse.ArgumentParser(description='Sky launcher/debugger') 327 parser = argparse.ArgumentParser(description='Sky launcher/debugger')
297 subparsers = parser.add_subparsers(help='sub-command help') 328 subparsers = parser.add_subparsers(help='sub-command help')
298 329
299 start_parser = subparsers.add_parser('start', 330 start_parser = subparsers.add_parser('start',
(...skipping 11 matching lines...) Expand all
311 start_parser.set_defaults(func=self.start_command) 342 start_parser.set_defaults(func=self.start_command)
312 343
313 stop_parser = subparsers.add_parser('stop', 344 stop_parser = subparsers.add_parser('stop',
314 help=('stop sky (as listed in %s)' % PID_FILE_PATH)) 345 help=('stop sky (as listed in %s)' % PID_FILE_PATH))
315 stop_parser.set_defaults(func=self.stop_command) 346 stop_parser.set_defaults(func=self.stop_command)
316 347
317 logcat_parser = subparsers.add_parser('logcat', 348 logcat_parser = subparsers.add_parser('logcat',
318 help=('dump sky-related logs from device')) 349 help=('dump sky-related logs from device'))
319 logcat_parser.set_defaults(func=self.logcat_command) 350 logcat_parser.set_defaults(func=self.logcat_command)
320 351
352 gdb_attach_parser = subparsers.add_parser('gdb_attach',
353 help='launch gdb and attach to gdbserver launched from start --gdb')
354 gdb_attach_parser.set_defaults(func=self.gdb_attach_command)
355
321 self._add_basic_command(subparsers, 'trace', '/trace', 356 self._add_basic_command(subparsers, 'trace', '/trace',
322 'toggle tracing') 357 'toggle tracing')
323 self._add_basic_command(subparsers, 'reload', '/reload', 358 self._add_basic_command(subparsers, 'reload', '/reload',
324 'reload the current page') 359 'reload the current page')
325 self._add_basic_command(subparsers, 'inspect', '/inspect', 360 self._add_basic_command(subparsers, 'inspect', '/inspect',
326 'stop the running sky instance') 361 'stop the running sky instance')
327 362
328 load_parser = subparsers.add_parser('load', 363 load_parser = subparsers.add_parser('load',
329 help='load a new page in the currently running sky') 364 help='load a new page in the currently running sky')
330 load_parser.add_argument('url_or_path', type=str) 365 load_parser.add_argument('url_or_path', type=str)
331 load_parser.set_defaults(func=self.load_command) 366 load_parser.set_defaults(func=self.load_command)
332 367
333 args = parser.parse_args() 368 args = parser.parse_args()
334 args.func(args) 369 args.func(args)
335 370
336 self._write_pid_file(PID_FILE_PATH, self.pids) 371 self._write_pid_file(PID_FILE_PATH, self.pids)
337 372
338 373
339 if __name__ == '__main__': 374 if __name__ == '__main__':
340 SkyDebugger().main() 375 SkyDebugger().main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698