From d50e63eaa71e568b3012e42e424be33157f0be6d Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Fri, 19 Jul 2019 13:50:38 -0700 Subject: [PATCH] Move debugger attached state into pydevd (#1610) * Move debugger attached state into pydevd * Fix linter * Fix tests --- .../pydevd/_pydevd_bundle/pydevd_api.py | 2 ++ .../pydevd_process_net_command_json.py | 10 ++++---- src/ptvsd/_vendored/pydevd/pydevd.py | 3 +++ src/ptvsd/server/attach_server.py | 23 +++++++++++++------ src/ptvsd/server/wrapper.py | 9 ++------ 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_api.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_api.py index 17668c4e..5f7adb04 100644 --- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_api.py +++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_api.py @@ -27,6 +27,7 @@ class PyDevdAPI(object): py_db.ready_to_run = True def notify_configuration_done(self, py_db): + py_db.dap_debugger_attached.set() py_db.on_configuration_done() def notify_disconnect(self, py_db): @@ -123,6 +124,7 @@ class PyDevdAPI(object): self.remove_all_breakpoints(py_db, filename='*') self.remove_all_exception_breakpoints(py_db) self.notify_disconnect(py_db) + py_db.dap_debugger_attached.clear() if resume_threads: self.request_resume_thread(thread_id='*') diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py index 751c312b..2103cfb0 100644 --- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py +++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py @@ -13,15 +13,15 @@ from _pydevd_bundle._debug_adapter import pydevd_base_schema from _pydevd_bundle._debug_adapter.pydevd_schema import ( CompletionsResponseBody, EvaluateResponseBody, ExceptionOptions, GotoTargetsResponseBody, ModulesResponseBody, ProcessEventBody, - ProcessEvent, Scope, ScopesResponseBody, SetExpressionResponseBody, - SetVariableResponseBody, SourceBreakpoint, SourceResponseBody, - VariablesResponseBody) + ProcessEvent, Scope, ScopesResponseBody, SetExpressionResponseBody, + SetVariableResponseBody, SourceBreakpoint, SourceResponseBody, + VariablesResponseBody) from _pydevd_bundle.pydevd_api import PyDevdAPI from _pydevd_bundle.pydevd_breakpoints import get_exception_class from _pydevd_bundle.pydevd_comm_constants import ( CMD_PROCESS_EVENT, CMD_RETURN, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO, - CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, - CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE) + CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, + CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE) from _pydevd_bundle.pydevd_constants import DebugInfoHolder, IS_WINDOWS from _pydevd_bundle.pydevd_filtering import ExcludeFilter from _pydevd_bundle.pydevd_json_debug_options import _extract_debug_options diff --git a/src/ptvsd/_vendored/pydevd/pydevd.py b/src/ptvsd/_vendored/pydevd/pydevd.py index 2948cffb..44580a60 100644 --- a/src/ptvsd/_vendored/pydevd/pydevd.py +++ b/src/ptvsd/_vendored/pydevd/pydevd.py @@ -515,6 +515,9 @@ class PyDB(object): self._exclude_by_filter_cache = {} self._apply_filter_cache = {} + # State for use with DAP based connections + self.dap_debugger_attached = threading.Event() + def on_configuration_done(self): ''' Note: only called when using the DAP (Debug Adapter Protocol). diff --git a/src/ptvsd/server/attach_server.py b/src/ptvsd/server/attach_server.py index def6903c..bf51f76c 100644 --- a/src/ptvsd/server/attach_server.py +++ b/src/ptvsd/server/attach_server.py @@ -10,8 +10,6 @@ from ptvsd.server._remote import ( attach as ptvsd_attach, enable_attach as ptvsd_enable_attach, ) -from ptvsd.server.wrapper import debugger_attached - import pydevd from _pydevd_bundle.pydevd_constants import get_global_debugger from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame @@ -39,7 +37,13 @@ def wait_for_attach(timeout=None): The timeout for the operation in seconds (or fractions thereof). """ ptvsd.server.log.info('wait_for_attach{0!r}', (timeout,)) - debugger_attached.wait(timeout) + dbg = get_global_debugger() + if bool(dbg): + dbg.dap_debugger_attached.wait(timeout) + else: + msg = 'wait_for_attach() called before enable_attach().' + ptvsd.server.log.info(msg) + raise AssertionError(msg) def enable_attach(address=(DEFAULT_HOST, DEFAULT_PORT), redirect_output=None, log_dir=None): @@ -77,7 +81,7 @@ def enable_attach(address=(DEFAULT_HOST, DEFAULT_PORT), redirect_output=None, lo if log_dir: ptvsd.common.options.log_dir = log_dir ptvsd.server.log.to_file() - ptvsd.server.log.info('enable_attach{0!r}', (address, redirect_output)) + ptvsd.server.log.info('enable_attach{0!r}', (address,)) if redirect_output is not None: ptvsd.server.log.info('redirect_output deprecation warning.') @@ -87,7 +91,9 @@ def enable_attach(address=(DEFAULT_HOST, DEFAULT_PORT), redirect_output=None, lo ptvsd.server.log.info('enable_attach() ignored - already attached.') return - debugger_attached.clear() + dbg = get_global_debugger() + if bool(dbg): + dbg.dap_debugger_attached.clear() # Ensure port is int port = address[1] @@ -127,7 +133,9 @@ def attach(address, redirect_output=None, log_dir=None): ptvsd.server.log.info('attach() ignored - already attached.') return - debugger_attached.clear() + dbg = get_global_debugger() + if bool(dbg): + dbg.dap_debugger_attached.clear() # Ensure port is int port = address[1] @@ -138,7 +146,8 @@ def attach(address, redirect_output=None, log_dir=None): def is_attached(): """Returns ``True`` if debugger is attached, ``False`` otherwise.""" - return debugger_attached.isSet() + dbg = get_global_debugger() + return bool(dbg) and dbg.dap_debugger_attached.is_set() def break_into_debugger(): diff --git a/src/ptvsd/server/wrapper.py b/src/ptvsd/server/wrapper.py index 466fac34..72b81fe4 100644 --- a/src/ptvsd/server/wrapper.py +++ b/src/ptvsd/server/wrapper.py @@ -48,9 +48,6 @@ from ptvsd.server.socket import TimeoutError # noqa WAIT_FOR_THREAD_FINISH_TIMEOUT = 1 # seconds -debugger_attached = threading.Event() - - def NOOP(*args, **kwargs): pass @@ -876,7 +873,6 @@ class VSCLifecycleMsgProcessor(VSCodeMessageProcessorBase): def on_disconnect(self, request, args): multiproc.kill_subprocesses() - debugger_attached.clear() self._restart_debugger = args.get('restart', False) # TODO: docstring @@ -1112,7 +1108,6 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor): self._process_debug_options(self.debug_options) self._forward_request_to_pydevd(request, args, send_response=False) - debugger_attached.set() self._notify_debugger_ready() @@ -1290,7 +1285,7 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor): @async_handler def on_pause(self, request, args): # Pause requests cannot be serviced until pydevd is fully initialized. - if not debugger_attached.isSet(): + if not ptvsd.is_attached(): self.send_response( request, success=False, @@ -1468,7 +1463,7 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor): } ''' # When we receive the thread on tests (due to a threads request), it's possible - # that the `debugger_attached` is still unset (but we should report about the + # that the `is_attached` return false (but we should report about the # thread creation anyways). tid = args['body']['threadId'] self.send_event('thread', reason='started', threadId=tid)