def _setup_channel(self): self.stream = LoggingJsonStream(JsonIOStream.from_socket(self.socket), 'ptvsd#%d' % self.ptvsd_port) handlers = MessageHandlers(request=self._process_request, event=self._process_event) self.channel = JsonMessageChannel(self.stream, handlers) self.channel.start() self.connected.set()
def _subprocess_listener(): counter = itertools.count(1) while subprocess_listener_socket: try: (sock, _) = subprocess_listener_socket.accept() except Exception: break stream = JsonIOStream.from_socket(sock) _handle_subprocess(next(counter), stream)
def prepare_to_run(self, perform_handshake=True, filename=None, module=None): """Spawns ptvsd using the configured method, telling it to execute the provided Python file or module, and establishes a message channel to it. If perform_handshake is True, calls self.handshake() before returning. """ argv = [sys.executable] if self.method != 'attach_pid': argv += ['-m', 'ptvsd'] if self.method == 'attach_socket': if self.ptvsd_port is None: self.ptvsd_port = 5678 argv += ['--port', str(self.ptvsd_port)] else: port = self._listen() argv += ['--host', 'localhost', '--port', str(port)] if filename: assert not module argv += [filename] elif module: assert not filename argv += ['-m', module] env = os.environ.copy() env.update({'PYTHONPATH': PTVSD_SYS_PATH}) print('Spawning %r' % argv) self.process = subprocess.Popen(argv, env=env, stdin=subprocess.PIPE) if self.ptvsd_port: # ptvsd will take some time to spawn and start listening on the port, # so just hammer at it until it responds (or we time out). while not self.socket: try: self._connect() except socket.error: pass time.sleep(0.1) else: self.connected.wait() assert self.socket self.stream = LoggingJsonStream(JsonIOStream.from_socket(self.socket)) handlers = MessageHandlers(request=self._process_request, event=self._process_event) self.channel = JsonMessageChannel(self.stream, handlers) self.channel.start() if perform_handshake: self.handshake()
def _backchannel_worker(self): print('Listening for incoming backchannel connection for bchan#%d' % self.ptvsd_port) sock = None try: sock, _ = self.backchannel_socket.accept() except socket.timeout: assert sock is not None, 'bchan#%r timed out!' % self.ptvsd_port print('Incoming bchan#%d backchannel connection accepted' % self.ptvsd_port) sock.settimeout(None) self._backchannel_stream = LoggingJsonStream(JsonIOStream.from_socket(sock), 'bchan#%d' % self.ptvsd_port) self.backchannel_established.set()
def _subprocess_listener(): counter = itertools.count(1) while subprocess_listener_socket: try: (sock, _) = subprocess_listener_socket.accept() except Exception: break n = next(counter) name = 'subprocess-{}'.format(n) ptvsd.log.debug('Accepted incoming connection from {0}', name) stream = JsonIOStream.from_socket(sock, name=name) _handle_subprocess(n, stream)
def notify_root(port): assert options.subprocess_of debug('Subprocess %d notifying root process at port %d' % (os.getpid(), options.subprocess_notify)) conn = create_client() conn.connect(('localhost', options.subprocess_notify)) stream = JsonIOStream.from_socket(conn) channel = JsonMessageChannel(stream) channel.start() # Send the notification about ourselves to root, and wait for it to tell us # whether an incoming connection is anticipated. This will be true if root # had successfully propagated the notification to the IDE, and false if it # couldn't do so (e.g. because the IDE is not attached). There's also the # possibility that connection to root will just drop, e.g. if it crashes - # in that case, just exit immediately. request = channel.send_request( 'ptvsd_subprocess', { 'parentProcessId': options.subprocess_of, 'processId': os.getpid(), 'port': port, }) try: response = request.wait_for_response() except Exception: print('Failed to send subprocess notification; exiting', file=sys.__stderr__) traceback.print_exc() sys.exit(0) # Keep the channel open until we exit - root process uses open channels to keep # track of which subprocesses are alive and which are not. atexit.register(lambda: channel.close()) if not response['incomingConnection']: debugger = get_global_debugger() while debugger is None: time.sleep(0.1) debugger = get_global_debugger() debugger.ready_to_run = True
def notify_root(port): assert options.subprocess_of debug('Subprocess %d notifying root process at port %d' % (os.getpid(), options.subprocess_notify)) conn = create_client() conn.connect(('localhost', options.subprocess_notify)) stream = JsonIOStream.from_socket(conn) channel = JsonMessageChannel(stream) channel.start() # Send the notification about ourselves to root, and wait for it to tell us # whether an incoming connection is anticipated. This will be true if root # had successfully propagated the notification to the IDE, and false if it # couldn't do so (e.g. because the IDE is not attached). There's also the # possibility that connection to root will just drop, e.g. if it crashes - # in that case, just exit immediately. request = channel.send_request('ptvsd_subprocess', { 'parentProcessId': options.subprocess_of, 'processId': os.getpid(), 'port': port, }) try: response = request.wait_for_response() except Exception: print('Failed to send subprocess notification; exiting', file=sys.__stderr__) traceback.print_exc() sys.exit(0) # Keep the channel open until we exit - root process uses open channels to keep # track of which subprocesses are alive and which are not. atexit.register(lambda: channel.close()) if not response['incomingConnection']: debugger = get_global_debugger() while debugger is None: time.sleep(0.1) debugger = get_global_debugger() debugger.ready_to_run = True
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See LICENSE in the project root # for license information. from __future__ import print_function, with_statement, absolute_import """Imported from test code that runs under ptvsd, and allows that code to communcate back to the test. Works in conjunction with debug_session fixture and its backchannel method.""" import os import socket from ptvsd.messaging import JsonIOStream port = int(os.getenv('PTVSD_BACKCHANNEL_PORT')) # print('Connecting to bchan#%d' % port) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('localhost', port)) stream = JsonIOStream.from_socket(sock) def read_json(): return stream.read_json() def write_json(value): stream.write_json(value)
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See LICENSE in the project root # for license information. from __future__ import print_function, with_statement, absolute_import """Imported from test code that runs under ptvsd, and allows that code to communcate back to the test. Works in conjunction with debug_session fixture and its backchannel method.""" import os import socket import ptvsd.log from ptvsd.messaging import JsonIOStream port = int(os.getenv('PTVSD_BACKCHANNEL_PORT')) ptvsd.log.debug('Connecting to bchan#{0}', port) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('localhost', port)) stream = JsonIOStream.from_socket(sock, name='test') def read_json(): return stream.read_json() def write_json(value): stream.write_json(value)