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 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 logging.info('No pid for %s, nothing to do.' % name) | 281 logging.info('No pid for %s, nothing to do.' % name) |
282 return | 282 return |
283 logging.info('Killing %s (%d).' % (name, pid)) | 283 logging.info('Killing %s (%d).' % (name, pid)) |
284 try: | 284 try: |
285 os.kill(pid, signal.SIGTERM) | 285 os.kill(pid, signal.SIGTERM) |
286 except OSError: | 286 except OSError: |
287 logging.info('%s (%d) already gone.' % (name, pid)) | 287 logging.info('%s (%d) already gone.' % (name, pid)) |
288 | 288 |
289 def stop_command(self, args): | 289 def stop_command(self, args): |
290 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. | 290 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. |
291 # self._send_command_to_sky('/quit') | 291 # self._run_basic_command('/quit') |
292 | 292 |
293 self._kill_if_exists('sky_server_pid', 'sky_server') | 293 self._kill_if_exists('sky_server_pid', 'sky_server') |
294 | 294 |
295 # We could be much more surgical here: | 295 # We could be much more surgical here: |
296 if 'remote_sky_server_port' in self.pids: | 296 if 'remote_sky_server_port' in self.pids: |
297 device = android_commands.AndroidCommands( | 297 device = android_commands.AndroidCommands( |
298 self.pids['device_serial']) | 298 self.pids['device_serial']) |
299 forwarder.Forwarder.UnmapAllDevicePorts(device) | 299 forwarder.Forwarder.UnmapAllDevicePorts(device) |
300 | 300 |
301 if 'remote_sky_command_port' in self.pids: | 301 if 'remote_sky_command_port' in self.pids: |
(...skipping 17 matching lines...) Expand all Loading... |
319 | 319 |
320 def load_command(self, args): | 320 def load_command(self, args): |
321 if not urlparse.urlparse(args.url_or_path).scheme: | 321 if not urlparse.urlparse(args.url_or_path).scheme: |
322 # The load happens on the remote device, use the remote port. | 322 # The load happens on the remote device, use the remote port. |
323 remote_sky_server_port = self.pids.get('remote_sky_server_port', | 323 remote_sky_server_port = self.pids.get('remote_sky_server_port', |
324 self.pids['sky_server_port']) | 324 self.pids['sky_server_port']) |
325 url = SkyServer.url_for_path(remote_sky_server_port, | 325 url = SkyServer.url_for_path(remote_sky_server_port, |
326 self.pids['sky_server_root'], args.url_or_path) | 326 self.pids['sky_server_root'], args.url_or_path) |
327 else: | 327 else: |
328 url = args.url_or_path | 328 url = args.url_or_path |
329 self._send_command_to_sky('/load', url) | 329 self._run_basic_command('/load', url) |
330 | 330 |
331 def _read_mojo_map(self): | 331 def _read_mojo_map(self): |
332 # TODO(eseidel): Does not work for android. | 332 # TODO(eseidel): Does not work for android. |
333 mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid'] | 333 mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid'] |
334 with open(mojo_map_path, 'r') as maps_file: | 334 with open(mojo_map_path, 'r') as maps_file: |
335 lines = maps_file.read().strip().split('\n') | 335 lines = maps_file.read().strip().split('\n') |
336 return dict(map(lambda line: line.split(' '), lines)) | 336 return dict(map(lambda line: line.split(' '), lines)) |
337 | 337 |
| 338 def stop_tracing_command(self, args): |
| 339 file_name = args.file_name |
| 340 trace = self._send_command_to_sky('/stop_tracing').content |
| 341 with open(file_name, "wb") as trace_file: |
| 342 trace_file.write(trace) |
| 343 print "Trace saved in %s" % file_name |
| 344 |
338 def stop_profiling_command(self, args): | 345 def stop_profiling_command(self, args): |
339 self._send_command_to_sky('/stop_profiling') | 346 self._run_basic_command('/stop_profiling') |
340 mojo_map = self._read_mojo_map() | 347 mojo_map = self._read_mojo_map() |
341 | 348 |
342 # TODO(eseidel): We should have a helper for resolving urls, etc. | 349 # TODO(eseidel): We should have a helper for resolving urls, etc. |
343 remote_server_port = self.pids.get('remote_sky_server_port', self.pids['
sky_server_port']) | 350 remote_server_port = self.pids.get('remote_sky_server_port', self.pids['
sky_server_port']) |
344 build_dir_url = SkyServer.url_for_path( | 351 build_dir_url = SkyServer.url_for_path( |
345 remote_server_port, | 352 remote_server_port, |
346 self.pids['sky_server_root'], | 353 self.pids['sky_server_root'], |
347 self.pids['build_dir']) | 354 self.pids['build_dir']) |
348 | 355 |
349 # Map /tmp cache paths to urls and then to local build_dir paths. | 356 # Map /tmp cache paths to urls and then to local build_dir paths. |
(...skipping 23 matching lines...) Expand all Loading... |
373 def _command_base_url(self): | 380 def _command_base_url(self): |
374 return 'http://localhost:%s' % self.pids['sky_command_port'] | 381 return 'http://localhost:%s' % self.pids['sky_command_port'] |
375 | 382 |
376 def _send_command_to_sky(self, command_path, payload=None): | 383 def _send_command_to_sky(self, command_path, payload=None): |
377 url = 'http://localhost:%s%s' % ( | 384 url = 'http://localhost:%s%s' % ( |
378 self.pids['sky_command_port'], command_path) | 385 self.pids['sky_command_port'], command_path) |
379 if payload: | 386 if payload: |
380 response = requests.post(url, payload) | 387 response = requests.post(url, payload) |
381 else: | 388 else: |
382 response = requests.get(url) | 389 response = requests.get(url) |
383 print response.text | 390 return response |
| 391 |
| 392 def _run_basic_command(self, command_path, payload=None): |
| 393 print self._send_command_to_sky(command_path, payload=payload).text |
384 | 394 |
385 # FIXME: These could be made into a context object with __enter__/__exit__. | 395 # FIXME: These could be made into a context object with __enter__/__exit__. |
386 def _load_pid_file(self, path): | 396 def _load_pid_file(self, path): |
387 try: | 397 try: |
388 with open(path, 'r') as pid_file: | 398 with open(path, 'r') as pid_file: |
389 return json.load(pid_file) | 399 return json.load(pid_file) |
390 except: | 400 except: |
391 if os.path.exists(path): | 401 if os.path.exists(path): |
392 logging.warn('Failed to read pid file: %s' % path) | 402 logging.warn('Failed to read pid file: %s' % path) |
393 return {} | 403 return {} |
394 | 404 |
395 def _write_pid_file(self, path, pids): | 405 def _write_pid_file(self, path, pids): |
396 try: | 406 try: |
397 with open(path, 'w') as pid_file: | 407 with open(path, 'w') as pid_file: |
398 json.dump(pids, pid_file, indent=2, sort_keys=True) | 408 json.dump(pids, pid_file, indent=2, sort_keys=True) |
399 except: | 409 except: |
400 logging.warn('Failed to write pid file: %s' % path) | 410 logging.warn('Failed to write pid file: %s' % path) |
401 | 411 |
402 def _add_basic_command(self, subparsers, name, url_path, help_text): | 412 def _add_basic_command(self, subparsers, name, url_path, help_text): |
403 parser = subparsers.add_parser(name, help=help_text) | 413 parser = subparsers.add_parser(name, help=help_text) |
404 command = lambda args: self._send_command_to_sky(url_path) | 414 command = lambda args: self._run_basic_command(url_path) |
405 parser.set_defaults(func=command) | 415 parser.set_defaults(func=command) |
406 | 416 |
407 def _wait_for_sky_command_port(self): | 417 def _wait_for_sky_command_port(self): |
408 tries = 0 | 418 tries = 0 |
409 while True: | 419 while True: |
410 try: | 420 try: |
411 self._send_command_to_sky('/') | 421 self._run_basic_command('/') |
412 return True | 422 return True |
413 except: | 423 except: |
414 tries += 1 | 424 tries += 1 |
415 if tries == 3: | 425 if tries == 3: |
416 logging.warn('Still waiting for sky on port %s' % | 426 logging.warn('Still waiting for sky on port %s' % |
417 self.pids['sky_command_port']) | 427 self.pids['sky_command_port']) |
418 if tries > 10: | 428 if tries > 10: |
419 return False | 429 return False |
420 time.sleep(1) | 430 time.sleep(1) |
421 | 431 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 logcat_parser.set_defaults(func=self.logcat_command) | 567 logcat_parser.set_defaults(func=self.logcat_command) |
558 | 568 |
559 print_crash_parser = subparsers.add_parser('print_crash', | 569 print_crash_parser = subparsers.add_parser('print_crash', |
560 help=('dump (and symbolicate) recent crash-stacks')) | 570 help=('dump (and symbolicate) recent crash-stacks')) |
561 print_crash_parser.set_defaults(func=self.print_crash_command) | 571 print_crash_parser.set_defaults(func=self.print_crash_command) |
562 | 572 |
563 gdb_attach_parser = subparsers.add_parser('gdb_attach', | 573 gdb_attach_parser = subparsers.add_parser('gdb_attach', |
564 help='launch gdb and attach to gdbserver launched from start --gdb') | 574 help='launch gdb and attach to gdbserver launched from start --gdb') |
565 gdb_attach_parser.set_defaults(func=self.gdb_attach_command) | 575 gdb_attach_parser.set_defaults(func=self.gdb_attach_command) |
566 | 576 |
567 self._add_basic_command(subparsers, 'trace', '/trace', | 577 self._add_basic_command(subparsers, 'start_tracing', '/start_tracing', |
568 'toggle tracing') | 578 'starts tracing the running sky instance') |
569 self._add_basic_command(subparsers, 'reload', '/reload', | 579 self._add_basic_command(subparsers, 'reload', '/reload', |
570 'reload the current page') | 580 'reload the current page') |
571 self._add_basic_command(subparsers, 'inspect', '/inspect', | 581 self._add_basic_command(subparsers, 'inspect', '/inspect', |
572 'start the inspector on the current page (Linux only)') | 582 'start the inspector on the current page (Linux only)') |
573 self._add_basic_command(subparsers, 'start_profiling', '/start_profiling
', | 583 self._add_basic_command(subparsers, 'start_profiling', '/start_profiling
', |
574 'starts profiling the running sky instance (Linux only)') | 584 'starts profiling the running sky instance (Linux only)') |
575 | 585 |
| 586 stop_tracing_parser = subparsers.add_parser('stop_tracing', |
| 587 help='stops tracing the running sky instance') |
| 588 stop_tracing_parser.add_argument('file_name', type=str, default='sky_vie
wer.trace') |
| 589 stop_tracing_parser.set_defaults(func=self.stop_tracing_command) |
| 590 |
576 stop_profiling_parser = subparsers.add_parser('stop_profiling', | 591 stop_profiling_parser = subparsers.add_parser('stop_profiling', |
577 help='stops profiling the running sky instance (Linux only)') | 592 help='stops profiling the running sky instance (Linux only)') |
578 stop_profiling_parser.set_defaults(func=self.stop_profiling_command) | 593 stop_profiling_parser.set_defaults(func=self.stop_profiling_command) |
579 | 594 |
580 load_parser = subparsers.add_parser('load', | 595 load_parser = subparsers.add_parser('load', |
581 help='load a new page in the currently running sky') | 596 help='load a new page in the currently running sky') |
582 load_parser.add_argument('url_or_path', type=str) | 597 load_parser.add_argument('url_or_path', type=str) |
583 load_parser.set_defaults(func=self.load_command) | 598 load_parser.set_defaults(func=self.load_command) |
584 | 599 |
585 args = parser.parse_args() | 600 args = parser.parse_args() |
586 args.func(args) | 601 args.func(args) |
587 | 602 |
588 self._write_pid_file(PID_FILE_PATH, self.pids) | 603 self._write_pid_file(PID_FILE_PATH, self.pids) |
589 | 604 |
590 | 605 |
591 if __name__ == '__main__': | 606 if __name__ == '__main__': |
592 SkyDebugger().main() | 607 SkyDebugger().main() |
OLD | NEW |