mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix #1510: [sys.monitoring] Deadlocks when breakpoints are hit
This commit is contained in:
parent
8ce0f35d75
commit
256967225e
2 changed files with 22 additions and 20 deletions
|
|
@ -38,6 +38,12 @@ class Thread:
|
|||
DAP "thread" event with "reason":"started".
|
||||
"""
|
||||
|
||||
is_traced: bool
|
||||
"""
|
||||
Whether this thread is traced. Threads are normally traced, but API clients
|
||||
can exclude a specific thread from tracing.
|
||||
"""
|
||||
|
||||
_last_id = 0
|
||||
_all: ClassVar[Dict[int, "Thread"]] = {}
|
||||
|
||||
|
|
@ -48,6 +54,7 @@ class Thread:
|
|||
"""
|
||||
self.python_thread = python_thread
|
||||
self.is_known_to_adapter = False
|
||||
self.is_traced = True
|
||||
|
||||
with _cvar:
|
||||
# Thread IDs are serialized as JSON numbers in DAP, which are handled as 64-bit
|
||||
|
|
@ -71,14 +78,6 @@ class Thread:
|
|||
"name": self.name,
|
||||
}
|
||||
|
||||
@property
|
||||
def is_debugpy_thread(self):
|
||||
return getattr(self.python_thread, "is_debugpy_thread", False)
|
||||
|
||||
@property
|
||||
def is_traced(self):
|
||||
return not self.is_debugpy_thread
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.python_thread.name
|
||||
|
|
@ -88,10 +87,13 @@ class Thread:
|
|||
"""
|
||||
Returns the DAP Thread object corresponding to the given Python thread, or for
|
||||
the current Python thread if None, creating it and reporting it to adapter if
|
||||
necessary.
|
||||
necessary. If the current thread is internal debugpy thread, returns None.
|
||||
"""
|
||||
|
||||
if python_thread is None:
|
||||
python_thread = threading.current_thread()
|
||||
if getattr(python_thread, "is_debugpy_thread", False):
|
||||
return None
|
||||
with _cvar:
|
||||
for thread in self._all.values():
|
||||
if thread.python_thread is python_thread:
|
||||
|
|
@ -118,7 +120,7 @@ class Thread:
|
|||
thread
|
||||
for python_thread in threading.enumerate()
|
||||
for thread in [Thread.from_python_thread(python_thread)]
|
||||
if thread.is_traced
|
||||
if thread is not None and thread.is_traced
|
||||
]
|
||||
|
||||
def make_known_to_adapter(self):
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ class Tracer:
|
|||
|
||||
def _trace_line(self, code: CodeType, line_number: int):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return self.monitoring.DISABLE
|
||||
|
||||
self.log.debug(f"sys.monitoring event: LINE({line_number}, {code})")
|
||||
|
|
@ -347,19 +347,19 @@ class Tracer:
|
|||
|
||||
def _trace_py_start(self, code: CodeType, ip: int):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return self.monitoring.DISABLE
|
||||
self.log.debug(f"sys.monitoring event: PY_START({code}, {ip})")
|
||||
|
||||
def _trace_py_resume(self, code: CodeType, ip: int):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return self.monitoring.DISABLE
|
||||
self.log.debug(f"sys.monitoring event: PY_RESUME({code}, {ip})")
|
||||
|
||||
def _trace_py_return(self, code: CodeType, ip: int, retval: object):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return self.monitoring.DISABLE
|
||||
self.log.debug(f"sys.monitoring event: PY_RETURN({code}, {ip})")
|
||||
# TODO: capture returned value to report it when client requests locals.
|
||||
|
|
@ -367,7 +367,7 @@ class Tracer:
|
|||
|
||||
def _trace_py_yield(self, code: CodeType, ip: int, retval: object):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return self.monitoring.DISABLE
|
||||
self.log.debug(f"sys.monitoring event: PY_YIELD({code}, {ip})")
|
||||
# TODO: capture yielded value to report it when client requests locals.
|
||||
|
|
@ -375,7 +375,7 @@ class Tracer:
|
|||
|
||||
def _trace_py_throw(self, code: CodeType, ip: int, exc: BaseException):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return
|
||||
self.log.debug(
|
||||
f"sys.monitoring event: PY_THROW({code}, {ip}, {type(exc).__qualname__})"
|
||||
|
|
@ -383,7 +383,7 @@ class Tracer:
|
|||
|
||||
def _trace_py_unwind(self, code: CodeType, ip: int, exc: BaseException):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return
|
||||
self.log.debug(
|
||||
f"sys.monitoring event: PY_UNWIND({code}, {ip}, {type(exc).__qualname__})"
|
||||
|
|
@ -391,7 +391,7 @@ class Tracer:
|
|||
|
||||
def _trace_raise(self, code: CodeType, ip: int, exc: BaseException):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return
|
||||
self.log.debug(
|
||||
f"sys.monitoring event: RAISE({code}, {ip}, {type(exc).__qualname__})"
|
||||
|
|
@ -399,7 +399,7 @@ class Tracer:
|
|||
|
||||
def _trace_reraise(self, code: CodeType, ip: int, exc: BaseException):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return
|
||||
self.log.debug(
|
||||
f"sys.monitoring event: RERAISE({code}, {ip}, {type(exc).__qualname__})"
|
||||
|
|
@ -407,7 +407,7 @@ class Tracer:
|
|||
|
||||
def _trace_exception_handled(self, code: CodeType, ip: int, exc: BaseException):
|
||||
thread = self.Thread.from_python_thread()
|
||||
if not thread.is_traced:
|
||||
if thread is None or not thread.is_traced:
|
||||
return
|
||||
self.log.debug(
|
||||
f"sys.monitoring event: EXCEPTION_HANDLED({code}, {ip}, {type(exc).__qualname__})"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue