def enable_attach(secret, address=('0.0.0.0', DEFAULT_PORT), certfile=None, keyfile=None, redirect_output=True): """Enables Python Tools for Visual Studio to attach to this process remotely to debug Python code. Parameters ---------- secret : str Used to validate the clients - only those clients providing the valid secret will be allowed to connect to this server. On client side, the secret is prepended to the Qualifier string, separated from the hostname by ``'@'``, e.g.: ``'[email protected]:5678'``. If secret is ``None``, there's no validation, and any client can connect freely. address : (str, int), optional Specifies the interface and port on which the debugging server should listen for TCP connections. It is in the same format as used for regular sockets of the `socket.AF_INET` family, i.e. a tuple of ``(hostname, port)``. On client side, the server is identified by the Qualifier string in the usual ``'hostname:port'`` format, e.g.: ``'myhost.cloudapp.net:5678'``. Default is ``('0.0.0.0', 5678)``. certfile : str, optional Used to enable SSL. If not specified, or if set to ``None``, the connection between this program and the debugger will be unsecure, and can be intercepted on the wire. If specified, the meaning of this parameter is the same as for `ssl.wrap_socket`. keyfile : str, optional Used together with `certfile` when SSL is enabled. Its meaning is the same as for ``ssl.wrap_socket``. redirect_output : bool, optional Specifies whether any output (on both `stdout` and `stderr`) produced by this program should be sent to the debugger. Default is ``True``. Notes ----- This function returns immediately after setting up the debugging server, and does not block program execution. If you need to block until debugger is attached, call `ptvsd.wait_for_attach`. The debugger can be detached and re-attached multiple times after `enable_attach` is called. This function can only be called once during the lifetime of the process. On a second call, `AttachAlreadyEnabledError` is raised. In circumstances where the caller does not control how many times the function will be called (e.g. when a script with a single call is run more than once by a hosting app or framework), the call should be wrapped in ``try..except``. Only the thread on which this function is called, and any threads that are created after it returns, will be visible in the debugger once it is attached. Any threads that are already running before this function is called will not be visible. """ if not ssl and (certfile or keyfile): raise ValueError( 'could not import the ssl module - SSL is not supported on this version of Python' ) if sys.platform == 'cli': import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError( 'IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.' ) global _attach_enabled if _attach_enabled: raise AttachAlreadyEnabledError( 'ptvsd.enable_attach() has already been called in this process.') _attach_enabled = True atexit.register(vspd.detach_process_and_notify_debugger) server = socket.socket(proto=socket.IPPROTO_TCP) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None raw_client = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side=True, ssl_version=ssl.PROTOCOL_TLSv1, certfile=certfile, keyfile=keyfile) write_bytes(client, PTVSDBG) write_int(client, PTVSDBG_VER) response = read_bytes(client, 7) if response != PTVSDBG: continue dbg_ver = read_int(client) if dbg_ver != PTVSDBG_VER: continue client_secret = read_string(client) if secret is None or secret == client_secret: write_bytes(client, ACPT) else: write_bytes(client, RJCT) continue response = read_bytes(client, 4) if response == INFO: try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) exe = sys.executable or '' write_string(client, exe) try: username = getpass.getuser() except AttributeError: username = '' write_string(client, username) try: impl = platform.python_implementation() except AttributeError: try: impl = sys.implementation.name except AttributeError: impl = 'Python' major, minor, micro, release_level, serial = sys.version_info os_and_arch = platform.system() if os_and_arch == "": os_and_arch = sys.platform try: if sys.maxsize > 2**32: os_and_arch += ' 64-bit' else: os_and_arch += ' 32-bit' except AttributeError: pass version = '%s %s.%s.%s (%s)' % (impl, major, minor, micro, os_and_arch) write_string(client, version) client.recv(1) elif response == ATCH: debug_options = vspd.parse_debug_options( read_string(client)) debug_options.setdefault('rules', []).append({ 'path': PY_ROOT, 'include': False, }) if redirect_output: debug_options.add('RedirectOutput') if vspd.DETACHED: write_bytes(client, ACPT) try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) major, minor, micro, release_level, serial = sys.version_info write_int(client, major) write_int(client, minor) write_int(client, micro) vspd.attach_process_from_socket(client, debug_options, report=True) vspd.mark_all_threads_for_break( vspd.STEPPING_ATTACH_BREAK) _attached.set() client = None else: write_bytes(client, RJCT) elif response == REPL: if not vspd.DETACHED: write_bytes(client, ACPT) vspd.connect_repl_using_socket(client) client = None else: write_bytes(client, RJCT) except (socket.error, OSError): pass finally: if client is not None: client.close() server_thread = threading.Thread(target=server_thread_func) server_thread.setDaemon(True) server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) vspd.intercept_threads(for_attach=True)
def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None, keyfile = None, redirect_output = True): """Enables Python Tools for Visual Studio to attach to this process remotely to debug Python code. Parameters ---------- secret : str Used to validate the clients - only those clients providing the valid secret will be allowed to connect to this server. On client side, the secret is prepended to the Qualifier string, separated from the hostname by ``'@'``, e.g.: ``'[email protected]:5678'``. If secret is ``None``, there's no validation, and any client can connect freely. address : (str, int), optional Specifies the interface and port on which the debugging server should listen for TCP connections. It is in the same format as used for regular sockets of the `socket.AF_INET` family, i.e. a tuple of ``(hostname, port)``. On client side, the server is identified by the Qualifier string in the usual ``'hostname:port'`` format, e.g.: ``'myhost.cloudapp.net:5678'``. Default is ``('0.0.0.0', 5678)``. certfile : str, optional Used to enable SSL. If not specified, or if set to ``None``, the connection between this program and the debugger will be unsecure, and can be intercepted on the wire. If specified, the meaning of this parameter is the same as for `ssl.wrap_socket`. keyfile : str, optional Used together with `certfile` when SSL is enabled. Its meaning is the same as for ``ssl.wrap_socket``. redirect_output : bool, optional Specifies whether any output (on both `stdout` and `stderr`) produced by this program should be sent to the debugger. Default is ``True``. Notes ----- This function returns immediately after setting up the debugging server, and does not block program execution. If you need to block until debugger is attached, call `ptvsd.wait_for_attach`. The debugger can be detached and re-attached multiple times after `enable_attach` is called. This function can only be called once during the lifetime of the process. On a second call, `AttachAlreadyEnabledError` is raised. In circumstances where the caller does not control how many times the function will be called (e.g. when a script with a single call is run more than once by a hosting app or framework), the call should be wrapped in ``try..except``. Only the thread on which this function is called, and any threads that are created after it returns, will be visible in the debugger once it is attached. Any threads that are already running before this function is called will not be visible. """ if not ssl and (certfile or keyfile): raise ValueError('could not import the ssl module - SSL is not supported on this version of Python') if sys.platform == 'cli': # Check that IronPython was launched with -X:Frames and -X:Tracing, since we can't register our trace # func on the thread that calls enable_attach otherwise import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError('IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.') global _attach_enabled if _attach_enabled: raise AttachAlreadyEnabledError('ptvsd.enable_attach() has already been called in this process.') _attach_enabled = True if redirect_output: vspd.enable_output_redirection() atexit.register(vspd.detach_process_and_notify_debugger) server = socket.socket() server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None raw_client = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side = True, ssl_version = ssl.PROTOCOL_TLSv1, certfile = certfile, keyfile = keyfile) write_bytes(client, PTVSDBG) write_int(client, PTVSDBG_VER) response = read_bytes(client, 7) if response != PTVSDBG: continue dbg_ver = read_int(client) if dbg_ver != PTVSDBG_VER: continue client_secret = read_string(client) if secret is None or secret == client_secret: write_bytes(client, ACPT) else: write_bytes(client, RJCT) continue response = read_bytes(client, 4) if response == INFO: try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) exe = sys.executable or '' write_string(client, exe) try: username = getpass.getuser() except AttributeError: username = '' write_string(client, username) try: impl = platform.python_implementation() except AttributeError: try: impl = sys.implementation.name except AttributeError: impl = 'Python' major, minor, micro, release_level, serial = sys.version_info os_and_arch = platform.system() if os_and_arch == "": os_and_arch = sys.platform try: if sys.maxsize > 2**32: os_and_arch += ' 64-bit' else: os_and_arch += ' 32-bit' except AttributeError: pass version = '%s %s.%s.%s (%s)' % (impl, major, minor, micro, os_and_arch) write_string(client, version) # Don't just drop the connection - let the debugger close it after it finishes reading. client.recv(1) elif response == ATCH: if vspd.DETACHED: write_bytes(client, ACPT) try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) major, minor, micro, release_level, serial = sys.version_info write_int(client, major) write_int(client, minor) write_int(client, micro) vspd.attach_process_from_socket(client, report = True) vspd.mark_all_threads_for_break(vspd.STEPPING_ATTACH_BREAK) _attached.set() client = None else: write_bytes(client, RJCT) elif response == REPL: if not vspd.DETACHED: write_bytes(client, ACPT) vspd.connect_repl_using_socket(client) client = None else: write_bytes(client, RJCT) except (socket.error, OSError): pass finally: if client is not None: client.close() server_thread = threading.Thread(target = server_thread_func) server_thread.daemon = True server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) vspd.intercept_threads(for_attach = True)
def enable_attach(secret, address = ('0.0.0.0', 5678), certfile = None, keyfile = None, redirect_output = True): """Enables Python Tools for Visual Studio to attach to this process remotely to debug Python code. The secret parameter is used to validate the clients - only those clients providing the valid secret will be allowed to connect to this server. On client side, the secret is prepended to the Qualifier string, separated from the hostname by '@', e.g.: [email protected]:5678. If secret is None, there's no validation, and any client can connect freely. The address parameter specifies the interface and port on which the debugging server should listen for TCP connections. It is in the same format as used for regular sockets of the AF_INET family, i.e. a tuple of (hostname, port). On client side, the server is identified by the Qualifier string in the usual hostname:port format, e.g.: myhost.cloudapp.net:5678. The certfile parameter is used to enable SSL. If not specified, or if set to None, the connection between this program and the debugger will be unsecure, and can be intercepted on the wire. If specified, the meaning of this parameter is the same as for ssl.wrap_socket. The keyfile parameter is used together with certfile when SSL is enabled. Its meaning is the same as for ssl.wrap_socket. The redirect_output parameter specifies whether any output (on both stdout and stderr) produced by this program should be sent to the debugger. This function returns immediately after setting up the debugging server, and does not block program execution. If you need to block until debugger is attached, call ptvsd.wait_for_attach. The debugger can be detached and re-attached multiple times after enable_attach is called. Only the thread on which this function is called, and any threads that are created after it returns, will be visible in the debugger once it is attached. Any threads that are already running before this function is called will not be visible. """ if not ssl and (certfile or keyfile): raise ValueError('could not import the ssl module - SSL is not supported on this version of Python') if sys.platform == 'cli': # Check that IronPython was launched with -X:Frames and -X:Tracing, since we can't register our trace # func on the thread that calls enable_attach otherwise import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError('IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.') if redirect_output: _vspd.enable_output_redirection() atexit.register(_vspd.detach_process_and_notify_debugger) server = socket.socket() server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None raw_client = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side = True, ssl_version = ssl.PROTOCOL_TLSv1, certfile = certfile, keyfile = keyfile) client.sendall(PTVSDBG) _vspd.write_int(client, PTVSDBG_VER) response = client.recv(7) if response != PTVSDBG: continue dbg_ver = _vspd.read_int(client) if dbg_ver != PTVSDBG_VER: continue client_secret = _vspd.read_string(client) if secret is None or secret == client_secret: client.sendall(ACPT) else: client.sendall(RJCT) continue response = client.recv(4) if response == INFO: try: pid = os.getpid() except AttributeError: pid = 0 _vspd.write_int(client, pid) exe = sys.executable or '' _vspd.write_string(client, exe) try: username = getpass.getuser() except AttributeError: username = '' _vspd.write_string(client, username) try: impl = platform.python_implementation() except AttributeError: try: impl = sys.implementation.name except AttributeError: impl = 'Python' major, minor, micro, release_level, serial = sys.version_info os_and_arch = platform.system() if os_and_arch == "": os_and_arch = sys.platform try: if sys.maxsize > 2**32: os_and_arch += ' 64-bit' else: os_and_arch += ' 32-bit' except AttributeError: pass version = '%s %s.%s.%s (%s)' % (impl, major, minor, micro, os_and_arch) _vspd.write_string(client, version) elif response == ATCH: if _vspd.DETACHED: client.send(ACPT) major, minor, micro, release_level, serial = sys.version_info _vspd.write_int(client, major) _vspd.write_int(client, minor) _vspd.write_int(client, micro) _vspd.attach_process_from_socket(client, report = True) _vspd.mark_all_threads_for_break(_vspd.STEPPING_ATTACH_BREAK) _attached.set() client = None else: client.send(RJCT) elif response == REPL: if not _vspd.DETACHED: client.send(ACPT) _vspd.connect_repl_using_socket(client) client = None else: client.send(RJCT) except (socket.error, OSError): pass finally: if client is not None: client.close() server_thread = threading.Thread(target = server_thread_func) server_thread.daemon = True server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = _vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) _vspd.intercept_threads(for_attach = True)
def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None, keyfile = None, redirect_output = True): if not ssl and (certfile or keyfile): raise ValueError('could not import the ssl module - SSL is not supported on this version of Python') if sys.platform == 'cli': # Check that IronPython was launched with -X:Frames and -X:Tracing, since we can't register our trace # func on the thread that calls enable_attach otherwise import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension('py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError('IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.') global _attach_enabled if _attach_enabled: raise AttachAlreadyEnabledError('ptvsd.enable_attach() has already been called in this process.') _attach_enabled = True atexit.register(vspd.detach_process_and_notify_debugger) server = socket.socket(proto=socket.IPPROTO_TCP) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None raw_client = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side = True, ssl_version = ssl.PROTOCOL_TLSv1, certfile = certfile, keyfile = keyfile) write_bytes(client, PTVSDBG) write_int(client, PTVSDBG_VER) response = read_bytes(client, 7) if response != PTVSDBG: continue dbg_ver = read_int(client) if dbg_ver != PTVSDBG_VER: continue client_secret = read_string(client) if secret is None or secret == client_secret: write_bytes(client, ACPT) else: write_bytes(client, RJCT) continue response = read_bytes(client, 4) if response == INFO: try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) exe = sys.executable or '' write_string(client, exe) try: username = getpass.getuser() except AttributeError: username = '' write_string(client, username) try: impl = platform.python_implementation() except AttributeError: try: impl = sys.implementation.name except AttributeError: impl = 'Python' major, minor, micro, release_level, serial = sys.version_info os_and_arch = platform.system() if os_and_arch == "": os_and_arch = sys.platform try: if sys.maxsize > 2**32: os_and_arch += ' 64-bit' else: os_and_arch += ' 32-bit' except AttributeError: pass version = '%s %s.%s.%s (%s)' % (impl, major, minor, micro, os_and_arch) write_string(client, version) # Don't just drop the connection - let the debugger close it after it finishes reading. client.recv(1) elif response == ATCH: debug_options = vspd.parse_debug_options(read_string(client)) debug_options.setdefault('rules', []).append({ 'path': PY_ROOT, 'include': False, }) if redirect_output: debug_options.add('RedirectOutput') if vspd.DETACHED: write_bytes(client, ACPT) try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) major, minor, micro, release_level, serial = sys.version_info write_int(client, major) write_int(client, minor) write_int(client, micro) vspd.attach_process_from_socket(client, debug_options, report = True) vspd.mark_all_threads_for_break(vspd.STEPPING_ATTACH_BREAK) _attached.set() client = None else: write_bytes(client, RJCT) elif response == REPL: if not vspd.DETACHED: write_bytes(client, ACPT) vspd.connect_repl_using_socket(client) client = None else: write_bytes(client, RJCT) except (socket.error, OSError): pass finally: if client is not None: client.close() server_thread = threading.Thread(target = server_thread_func) server_thread.setDaemon(True) server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) vspd.intercept_threads(for_attach = True)
def enable_attach(secret, address=('0.0.0.0', DEFAULT_PORT), certfile=None, keyfile=None, redirect_output=True): """Enables Visual Studio to attach to this process remotely to debug Python code. Parameters ---------- secret : str Used to validate the clients - only those clients providing the valid secret will be allowed to connect to this server. On client side, the secret is prepended to the Qualifier string, separated from the hostname by ``'@'``, e.g.: ``'[email protected]:5678'``. If secret is ``None``, there's no validation, and any client can connect freely. address : (str, int), optional Specifies the interface and port on which the debugging server should listen for TCP connections. It is in the same format as used for regular sockets of the `socket.AF_INET` family, i.e. a tuple of ``(hostname, port)``. On client side, the server is identified by the Qualifier string in the usual ``'hostname:port'`` format, e.g.: ``'myhost.cloudapp.net:5678'``. Default is ``('0.0.0.0', 5678)``. certfile : str, optional Used to enable SSL. If not specified, or if set to ``None``, the connection between this program and the debugger will be unsecure, and can be intercepted on the wire. If specified, the meaning of this parameter is the same as for `ssl.wrap_socket`. keyfile : str, optional Used together with `certfile` when SSL is enabled. Its meaning is the same as for ``ssl.wrap_socket``. redirect_output : bool, optional Specifies whether any output (on both `stdout` and `stderr`) produced by this program should be sent to the debugger. Default is ``True``. Notes ----- This function returns immediately after setting up the debugging server, and does not block program execution. If you need to block until debugger is attached, call `ptvsd.wait_for_attach`. The debugger can be detached and re-attached multiple times after `enable_attach` is called. This function can only be called once during the lifetime of the process. On a second call, `AttachAlreadyEnabledError` is raised. In circumstances where the caller does not control how many times the function will be called (e.g. when a script with a single call is run more than once by a hosting app or framework), the call should be wrapped in ``try..except``. Only the thread on which this function is called, and any threads that are created after it returns, will be visible in the debugger once it is attached. Any threads that are already running before this function is called will not be visible. """ if not ssl and (certfile or keyfile): raise ValueError( 'could not import the ssl module - SSL is not supported on this version of Python' ) if sys.platform == 'cli': # Check that IronPython was launched with -X:Frames and -X:Tracing, since we can't register our trace # func on the thread that calls enable_attach otherwise import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError( 'IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.' ) global _attach_enabled if _attach_enabled: raise AttachAlreadyEnabledError( 'ptvsd.enable_attach() has already been called in this process.') _attach_enabled = True atexit.register(vspd.detach_process_and_notify_debugger) server = socket.socket(proto=socket.IPPROTO_TCP) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None connection = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side=True, ssl_version=ssl.PROTOCOL_TLSv1, certfile=certfile, keyfile=keyfile) connection = AttachLoop(client, secret, redirect_output, None) connection.send_event( name='legacyRemoteConnected', debuggerName=PTVSDBG, debuggerProtocolVersion=PTVSDBG_VER, ) connection.process_messages() except (socket.error, OSError): pass finally: if connection: connection.close() server_thread = threading.Thread(target=server_thread_func) server_thread.setDaemon(True) server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) vspd.intercept_threads(for_attach=True)
def enable_attach(secret, address=('0.0.0.0', DEFAULT_PORT), certfile=None, keyfile=None, redirect_output=True): """Enables Python Tools for Visual Studio to attach to this process remotely to debug Python code. The secret parameter is used to validate the clients - only those clients providing the valid secret will be allowed to connect to this server. On client side, the secret is prepended to the Qualifier string, separated from the hostname by '@', e.g.: [email protected]:5678. If secret is None, there's no validation, and any client can connect freely. The address parameter specifies the interface and port on which the debugging server should listen for TCP connections. It is in the same format as used for regular sockets of the AF_INET family, i.e. a tuple of (hostname, port). On client side, the server is identified by the Qualifier string in the usual hostname:port format, e.g.: myhost.cloudapp.net:5678. The certfile parameter is used to enable SSL. If not specified, or if set to None, the connection between this program and the debugger will be unsecure, and can be intercepted on the wire. If specified, the meaning of this parameter is the same as for ssl.wrap_socket. The keyfile parameter is used together with certfile when SSL is enabled. Its meaning is the same as for ssl.wrap_socket. The redirect_output parameter specifies whether any output (on both stdout and stderr) produced by this program should be sent to the debugger. This function returns immediately after setting up the debugging server, and does not block program execution. If you need to block until debugger is attached, call ptvsd.wait_for_attach. The debugger can be detached and re-attached multiple times after enable_attach is called. Only the thread on which this function is called, and any threads that are created after it returns, will be visible in the debugger once it is attached. Any threads that are already running before this function is called will not be visible. """ if not ssl and (certfile or keyfile): raise ValueError( 'could not import the ssl module - SSL is not supported on this version of Python' ) if sys.platform == 'cli': # Check that IronPython was launched with -X:Frames and -X:Tracing, since we can't register our trace # func on the thread that calls enable_attach otherwise import clr x_tracing = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Tracing x_frames = clr.GetCurrentRuntime().GetLanguageByExtension( 'py').Options.Frames if not x_tracing or not x_frames: raise RuntimeError( 'IronPython must be started with -X:Tracing and -X:Frames options to support PTVS remote debugging.' ) if redirect_output: vspd.enable_output_redirection() atexit.register(vspd.detach_process_and_notify_debugger) server = socket.socket() server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(address) server.listen(1) def server_thread_func(): while True: client = None raw_client = None try: client, addr = server.accept() if certfile: client = ssl.wrap_socket(client, server_side=True, ssl_version=ssl.PROTOCOL_TLSv1, certfile=certfile, keyfile=keyfile) write_bytes(client, PTVSDBG) write_int(client, PTVSDBG_VER) response = read_bytes(client, 7) if response != PTVSDBG: continue dbg_ver = read_int(client) if dbg_ver != PTVSDBG_VER: continue client_secret = read_string(client) if secret is None or secret == client_secret: write_bytes(client, ACPT) else: write_bytes(client, RJCT) continue response = read_bytes(client, 4) if response == INFO: try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) exe = sys.executable or '' write_string(client, exe) try: username = getpass.getuser() except AttributeError: username = '' write_string(client, username) try: impl = platform.python_implementation() except AttributeError: try: impl = sys.implementation.name except AttributeError: impl = 'Python' major, minor, micro, release_level, serial = sys.version_info os_and_arch = platform.system() if os_and_arch == "": os_and_arch = sys.platform try: if sys.maxsize > 2**32: os_and_arch += ' 64-bit' else: os_and_arch += ' 32-bit' except AttributeError: pass version = '%s %s.%s.%s (%s)' % (impl, major, minor, micro, os_and_arch) write_string(client, version) elif response == ATCH: if vspd.DETACHED: write_bytes(client, ACPT) try: pid = os.getpid() except AttributeError: pid = 0 write_int(client, pid) major, minor, micro, release_level, serial = sys.version_info write_int(client, major) write_int(client, minor) write_int(client, micro) vspd.attach_process_from_socket(client, report=True) vspd.mark_all_threads_for_break( vspd.STEPPING_ATTACH_BREAK) _attached.set() client = None else: write_bytes(client, RJCT) elif response == REPL: if not vspd.DETACHED: write_bytes(client, ACPT) vspd.connect_repl_using_socket(client) client = None else: write_bytes(client, RJCT) except (socket.error, OSError): pass finally: if client is not None: client.close() server_thread = threading.Thread(target=server_thread_func) server_thread.daemon = True server_thread.start() frames = [] f = sys._getframe() while True: f = f.f_back if f is None: break frames.append(f) frames.reverse() cur_thread = vspd.new_thread() for f in frames: cur_thread.push_frame(f) def replace_trace_func(): for f in frames: f.f_trace = cur_thread.trace_func replace_trace_func() sys.settrace(cur_thread.trace_func) vspd.intercept_threads(for_attach=True)