Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,8 @@ def start_client(host, port):
pass # May not be available everywhere.

try:
# 10 seconds default timeout
timeout = int(os.environ.get("PYDEVD_CONNECT_TIMEOUT", 10))
# 30 seconds default timeout
timeout = int(os.environ.get("PYDEVD_CONNECT_TIMEOUT", 30))
s.settimeout(timeout)
s.connect((host, port))
s.settimeout(None) # no timeout after connected
Expand Down
382 changes: 195 additions & 187 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1375,12 +1375,12 @@ cdef class PyDBFrame:


# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread, arg, prev_user_uncaught_exc_info):
def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread, arg, prev_user_uncaught_exc_info, is_unwind=False):
cdef bint should_stop;
cdef bint was_just_raised;
cdef list check_excs;
# ELSE
# def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught_exc_info):
# def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught_exc_info, is_unwind=False):
# ENDIF

should_stop = False
Expand All @@ -1397,7 +1397,7 @@ def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread
exception_breakpoint = None
try:
if py_db.plugin is not None:
result = py_db.plugin.exception_break(py_db, frame, thread, arg)
result = py_db.plugin.exception_break(py_db, frame, thread, arg, is_unwind)
if result:
should_stop, frame = result
except:
Expand All @@ -1417,7 +1417,7 @@ def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread
pass

else:
was_just_raised = just_raised(trace)
was_just_raised = trace.tb_next is None

# It was not handled by any plugin, lets check exception breakpoints.
check_excs = []
Expand Down
8 changes: 4 additions & 4 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1053,12 +1053,12 @@ def trace_dispatch(self, frame, event, arg):


# IFDEF CYTHON
# def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread, arg, prev_user_uncaught_exc_info):
# def should_stop_on_exception(py_db, PyDBAdditionalThreadInfo info, frame, thread, arg, prev_user_uncaught_exc_info, is_unwind=False):
# cdef bint should_stop;
# cdef bint was_just_raised;
# cdef list check_excs;
# ELSE
def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught_exc_info):
def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught_exc_info, is_unwind=False):
# ENDIF

should_stop = False
Expand All @@ -1075,7 +1075,7 @@ def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught
exception_breakpoint = None
try:
if py_db.plugin is not None:
result = py_db.plugin.exception_break(py_db, frame, thread, arg)
result = py_db.plugin.exception_break(py_db, frame, thread, arg, is_unwind)
if result:
should_stop, frame = result
except:
Expand All @@ -1095,7 +1095,7 @@ def should_stop_on_exception(py_db, info, frame, thread, arg, prev_user_uncaught
pass

else:
was_just_raised = just_raised(trace)
was_just_raised = trace.tb_next is None

# It was not handled by any plugin, lets check exception breakpoints.
check_excs = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from _pydev_bundle import pydev_log
import itertools
from typing import Any, Dict
import threading
from os.path import basename, splitext


Expand Down Expand Up @@ -46,27 +45,21 @@ def remove_exception_from_frame(frame):
FILES_WITH_IMPORT_HOOKS = ["pydev_monkey_qt.py", "pydev_import_hook.py"]


_thread_local_info = threading.local()
def flag_as_unwinding(trace):
_thread_local_info._unwinding_trace = trace

def just_raised(trace):
if trace is None:
return False

if hasattr(_thread_local_info, "_unwinding_trace") and _thread_local_info._unwinding_trace is trace:
return False

return trace.tb_next is None

def short_tb(exc_type, exc_value, exc_tb):
def short_tb(exc_tb):
traceback = []
while exc_tb:
traceback.append('{%r, %r, %r}' % (exc_tb.tb_frame.f_code.co_filename,
exc_tb.tb_frame.f_code.co_name,
exc_tb.tb_lineno))
exc_tb = exc_tb.tb_next
return 'Traceback: %s\nError: %s %r\n' % (' -> '.join(traceback), exc_type.__name__, str(exc_value))
return 'Traceback: %s\n' % (' -> '.join(traceback))

def short_frame(frame):
if frame is None:
Expand All @@ -76,6 +69,13 @@ def short_frame(frame):
name = splitext(basename(filename))[0]
return '%s::%s %s' % (name, frame.f_code.co_name, frame.f_lineno)

def short_stack(frame):
stack = []
while frame:
stack.append(short_frame(frame))
frame = frame.f_back
return 'Stack: %s\n' % (' -> '.join(stack))

def ignore_exception_trace(trace):
while trace is not None:
filename = trace.tb_frame.f_code.co_filename
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ def suspend(self, py_db, thread, frame, bp_type):

return None

def exception_break(self, py_db, frame, thread, arg):
def exception_break(self, py_db, frame, thread, arg, is_unwind=False):
for plugin in self.active_plugins:
ret = plugin.exception_break(py_db, frame, thread, arg)
ret = plugin.exception_break(py_db, frame, thread, arg, is_unwind)
if ret is not None:
return ret

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ def on_setfunctionbreakpoints_request(self, py_db, request):
expression = None

breakpoints_set = []
arguments.breakpoints = arguments.breakpoints or []
for bp in arguments.breakpoints:
hit_condition = self._get_hit_condition_expression(bp.get("hitCondition"))
condition = bp.get("condition")
Expand Down Expand Up @@ -805,7 +806,7 @@ def on_setbreakpoints_request(self, py_db, request):
btype = "jinja2-line"

breakpoints_set = []

arguments.breakpoints = arguments.breakpoints or []
for source_breakpoint in arguments.breakpoints:
source_breakpoint = SourceBreakpoint(**source_breakpoint)
line = source_breakpoint.line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
RETURN_VALUES_DICT,
PYTHON_SUSPEND,
)
from _pydevd_bundle.pydevd_frame_utils import short_tb, flag_as_unwinding, short_frame
from pydevd_file_utils import (
NORM_PATHS_AND_BASE_CONTAINER,
get_abs_path_real_path_and_base_from_file,
Expand All @@ -34,6 +33,7 @@
from _pydevd_bundle.pydevd_trace_dispatch import is_unhandled_exception
from _pydevd_bundle.pydevd_breakpoints import stop_on_unhandled_exception
from _pydevd_bundle.pydevd_utils import get_clsname_for_code
from _pydevd_bundle.pydevd_dont_trace_files import PYDEV_FILE

# fmt: off
# IFDEF CYTHON
Expand Down Expand Up @@ -172,65 +172,65 @@ def _get_bootstrap_frame(depth: int) -> Tuple[Optional[FrameType], bool]:

# fmt: off
# IFDEF CYTHON
# cdef _is_user_frame(frame: FrameType):
# cdef _get_unhandled_exception_frame(int depth):
# ELSE
def _is_user_frame(frame: FrameType) -> bool:
def _get_unhandled_exception_frame(depth: int) -> Optional[FrameType]:
# ENDIF
# fmt: on
if frame is None:
return False
try:
result = _thread_local_info.f_unhandled

# Make sure the result is from the same exception. That means the result is in the stack somewhere.
if result is not None:
orig = frame = _getframe(depth)
while result != frame and frame is not None:
frame = frame.f_back
if frame is not None:
return result
del _thread_local_info.f_unhandled
raise AttributeError("Unhandled frame from different exception")
except:
f_unhandled = _getframe(depth)

filename = frame.f_code.co_filename
name = splitext(basename(filename))[0]
while f_unhandled is not None and f_unhandled.f_back is not None:
f_back = f_unhandled.f_back
filename = f_back.f_code.co_filename
name = splitext(basename(filename))[0]

# When the frame is the bootstrap it is not a user frame.
if name == "threading":
if frame.f_code.co_name in ("__bootstrap", "_bootstrap", "__bootstrap_inner", "_bootstrap_inner", "run"):
return False
# When the back frame is the bootstrap (or if we have no back
# frame) then use this frame as the one to track.
if name == "threading":
if f_back.f_code.co_name in ("__bootstrap", "_bootstrap", "__bootstrap_inner", "_bootstrap_inner", "run"):
break

elif name == "pydev_monkey":
if frame.f_code.co_name == "__call__":
return False
elif name == "pydev_monkey":
if f_back.f_code.co_name == "__call__":
break

elif name == "pydevd":
if frame.f_code.co_name in ("_exec", "run", "main"):
return False
elif name == "pydevd":
if f_back.f_code.co_name in ("_exec", "run", "main"):
break

elif name == "pydevd_runpy":
if frame.f_code.co_name.startswith(("run", "_run")):
return False
elif name == "pydevd_runpy":
if f_back.f_code.co_name.startswith(("run", "_run")):
break

elif filename == "<frozen runpy>":
if frame.f_code.co_name.startswith(("run", "_run")):
return False
elif name == "<frozen runpy>":
if f_back.f_code.co_name.startswith(("run", "_run")):
break

elif name == 'runpy':
if frame.f_code.co_name.startswith(("run", "_run")):
return False
elif name == "runpy":
if f_back.f_code.co_name.startswith(("run", "_run")):
break

return True
f_unhandled = f_back

if f_unhandled is not None:
_thread_local_info.f_unhandled = f_unhandled
return _thread_local_info.f_unhandled

return f_unhandled

# fmt: off
# IFDEF CYTHON
# cdef _is_last_user_frame(frame: FrameType):
# ELSE
def _is_last_user_frame(frame: FrameType) -> bool:
# ENDIF
# fmt: on
# If this frame is not a user frame, then it can't be the last one
if not _is_user_frame(frame):
return False

# If this frame is the last frame, then it is the last one
if frame.f_back is None:
return True

# If the next frame is not a user frame, then this frame is the last one
if not _is_user_frame(frame.f_back):
return True

# Otherwise if the next frame is a user frame, then this frame is not the last one
return False

# fmt: off
# IFDEF CYTHON
Expand Down Expand Up @@ -832,8 +832,6 @@ def _unwind_event(code, instruction, exc):
if thread_info is None:
return

frame = _getframe(1)
arg = (type(exc), exc, exc.__traceback__)

py_db: object = GlobalDebuggerHolder.global_dbg
if py_db is None or py_db.pydb_disposed:
Expand All @@ -849,6 +847,8 @@ def _unwind_event(code, instruction, exc):
return

# print('_unwind_event', code, exc)
frame = _getframe(1)
arg = (type(exc), exc, exc.__traceback__)

has_caught_exception_breakpoint_in_pydb = (
py_db.break_on_caught_exceptions or py_db.break_on_user_uncaught_exceptions or py_db.has_plugin_exception_breaks
Expand All @@ -857,7 +857,7 @@ def _unwind_event(code, instruction, exc):

if has_caught_exception_breakpoint_in_pydb:
_should_stop, frame, user_uncaught_exc_info = should_stop_on_exception(
py_db, thread_info.additional_info, frame, thread_info.thread, arg, None
py_db, thread_info.additional_info, frame, thread_info.thread, arg, None, is_unwind=True
)
if user_uncaught_exc_info:
# TODO: Check: this may no longer be needed as in the unwind we know it's
Expand All @@ -876,8 +876,10 @@ def _unwind_event(code, instruction, exc):
return

break_on_uncaught_exceptions = py_db.break_on_uncaught_exceptions
if break_on_uncaught_exceptions and _is_last_user_frame(frame):
stop_on_unhandled_exception(py_db, thread_info.thread, thread_info.additional_info, arg)
if break_on_uncaught_exceptions:
if frame is _get_unhandled_exception_frame(1):
stop_on_unhandled_exception(py_db, thread_info.thread, thread_info.additional_info, arg)
return


# fmt: off
Expand Down Expand Up @@ -906,9 +908,6 @@ def _raise_event(code, instruction, exc):
if thread_info is None:
return

frame = _getframe(1)
arg = (type(exc), exc, exc.__traceback__)

py_db: object = GlobalDebuggerHolder.global_dbg
if py_db is None or py_db.pydb_disposed:
return
Expand All @@ -922,7 +921,8 @@ def _raise_event(code, instruction, exc):
if func_code_info.always_skip_code:
return

# print('_raise_event --- ', code, exc)
frame = _getframe(1)
arg = (type(exc), exc, exc.__traceback__)

# Compute the previous exception info (if any). We use it to check if the exception
# should be stopped
Expand All @@ -938,10 +938,6 @@ def _raise_event(code, instruction, exc):
if should_stop:
handle_exception(py_db, thread_info.thread, frame, arg, EXCEPTION_TYPE_HANDLED)

# Once we leave the raise event, we are no longer in the state of 'just_raised', so
# indicate that this traceback is for an exception in the unwinding state
flag_as_unwinding(exc.__traceback__)


# fmt: off
# IFDEF CYTHON
Expand Down Expand Up @@ -1342,6 +1338,10 @@ def _jump_event(code, from_offset, to_offset):
if py_db is None or py_db.pydb_disposed:
return monitor.DISABLE

# If we get another jump event, remove the extra check for the line event
if hasattr(_thread_local_info, "f_disable_next_line_if_match"):
del _thread_local_info.f_disable_next_line_if_match

if not thread_info.trace or not is_thread_alive(thread_info.thread):
# For thread-related stuff we can't disable the code tracing because other
# threads may still want it...
Expand Down Expand Up @@ -1370,7 +1370,7 @@ def _jump_event(code, from_offset, to_offset):
frame = _getframe(1)

# Disable the next line event as we're jumping to a line. The line event will be redundant.
_thread_local_info.f_disable_next_line_if_match = frame.f_lineno
_thread_local_info.f_disable_next_line_if_match = (func_code_info.co_filename, frame.f_lineno)

return _internal_line_event(func_code_info, frame, frame.f_lineno)

Expand Down Expand Up @@ -1405,11 +1405,11 @@ def _line_event(code, line):
return

if hasattr(_thread_local_info, "f_disable_next_line_if_match"):
if _thread_local_info.f_disable_next_line_if_match is line:
(co_filename, line_to_skip) = _thread_local_info.f_disable_next_line_if_match
del _thread_local_info.f_disable_next_line_if_match
if line_to_skip is line and co_filename == code.co_filename:
# If we're in a jump, we should skip this line event. The jump would have
# been considered a line event for this same line and we don't want to
# stop twice.
del _thread_local_info.f_disable_next_line_if_match
return

func_code_info: FuncCodeInfo = _get_func_code_info(code, 1)
Expand Down
Loading
Loading