@@ -169,6 +169,21 @@ def _get_bootstrap_frame(depth: int) -> Tuple[Optional[FrameType], bool]:
169169 return f_bootstrap , is_bootstrap_frame_internal
170170
171171
172+ # fmt: off
173+ # IFDEF CYTHON
174+ # cdef _clear_unhandled_exception_frame():
175+ # ELSE
176+ def _clear_unhandled_exception_frame ():
177+ # ENDIF
178+ # fmt: on
179+ # Invalidate the cache to prevent bugs on id reuse
180+ try :
181+ del _thread_local_info .f_unhandled_frame
182+ del _thread_local_info .f_unhandled_exc_id
183+ except AttributeError :
184+ pass
185+
186+
172187# fmt: off
173188# IFDEF CYTHON
174189# cdef _get_unhandled_exception_frame(exc, int depth):
@@ -178,11 +193,10 @@ def _get_unhandled_exception_frame(exc, depth: int) -> Optional[FrameType]:
178193# fmt: on
179194 try :
180195 # Unhandled frame has to be from the same exception.
181- if _thread_local_info .f_unhandled_exc is exc :
196+ if _thread_local_info .f_unhandled_exc_id is id ( exc ) :
182197 return _thread_local_info .f_unhandled_frame
183198 else :
184- del _thread_local_info .f_unhandled_frame
185- del _thread_local_info .f_unhandled_exc
199+ _clear_unhandled_exception_frame ()
186200 raise AttributeError ('Not the same exception' )
187201 except :
188202 f_unhandled = _getframe (depth )
@@ -222,7 +236,7 @@ def _get_unhandled_exception_frame(exc, depth: int) -> Optional[FrameType]:
222236
223237 if f_unhandled is not None :
224238 _thread_local_info .f_unhandled_frame = f_unhandled
225- _thread_local_info .f_unhandled_exc = exc
239+ _thread_local_info .f_unhandled_exc_id = id ( exc )
226240 return _thread_local_info .f_unhandled_frame
227241
228242 return f_unhandled
@@ -966,22 +980,29 @@ def _raise_event(code, instruction, exc):
966980 if func_code_info .always_skip_code :
967981 return
968982
969- frame = _getframe (1 )
970- arg = (type (exc ), exc , exc .__traceback__ )
983+ _clear_unhandled_exception_frame ()
971984
972- # Compute the previous exception info (if any). We use it to check if the exception
973- # should be stopped
974- prev_exc_info = _thread_local_info ._user_uncaught_exc_info if hasattr (_thread_local_info , "_user_uncaught_exc_info" ) else None
975- should_stop , frame , _user_uncaught_exc_info = should_stop_on_exception (
976- py_db , thread_info .additional_info , frame , thread_info .thread , arg , prev_exc_info
985+ has_caught_exception_breakpoint_in_pydb = (
986+ py_db .break_on_caught_exceptions or py_db .break_on_user_uncaught_exceptions or py_db .has_plugin_exception_breaks
977987 )
978988
979- # Save the current exception info for the next raise event.
980- _thread_local_info ._user_uncaught_exc_info = _user_uncaught_exc_info
989+ if has_caught_exception_breakpoint_in_pydb :
990+ frame = _getframe (1 )
991+ arg = (type (exc ), exc , exc .__traceback__ )
992+
993+ # Compute the previous exception info (if any). We use it to check if the exception
994+ # should be stopped
995+ prev_exc_info = _thread_local_info ._user_uncaught_exc_info if hasattr (_thread_local_info , "_user_uncaught_exc_info" ) else None
996+ should_stop , frame , _user_uncaught_exc_info = should_stop_on_exception (
997+ py_db , thread_info .additional_info , frame , thread_info .thread , arg , prev_exc_info
998+ )
999+
1000+ # Save the current exception info for the next raise event.
1001+ _thread_local_info ._user_uncaught_exc_info = _user_uncaught_exc_info
9811002
982- # print('!!!! should_stop (in raise)', should_stop)
983- if should_stop :
984- handle_exception (py_db , thread_info .thread , frame , arg , EXCEPTION_TYPE_HANDLED )
1003+ # print('!!!! should_stop (in raise)', should_stop)
1004+ if should_stop :
1005+ handle_exception (py_db , thread_info .thread , frame , arg , EXCEPTION_TYPE_HANDLED )
9851006
9861007
9871008# fmt: off
@@ -1869,13 +1890,13 @@ def update_monitor_events(suspend_requested: Optional[bool]=None) -> None:
18691890 # print('track RAISE')
18701891 monitor .register_callback (DEBUGGER_ID , monitor .events .RAISE , _raise_event )
18711892 monitor .register_callback (DEBUGGER_ID , monitor .events .PY_UNWIND , _unwind_event )
1893+ elif break_on_uncaught_exceptions :
1894+ required_events |= monitor .events .RAISE | monitor .events .PY_UNWIND
1895+ monitor .register_callback (DEBUGGER_ID , monitor .events .RAISE , _raise_event )
1896+ monitor .register_callback (DEBUGGER_ID , monitor .events .PY_UNWIND , _unwind_event )
18721897 else :
1873- if break_on_uncaught_exceptions :
1874- required_events |= monitor .events .PY_UNWIND
1875- monitor .register_callback (DEBUGGER_ID , monitor .events .PY_UNWIND , _unwind_event )
1876- else :
1877- monitor .register_callback (DEBUGGER_ID , monitor .events .RAISE , None )
1878- monitor .register_callback (DEBUGGER_ID , monitor .events .PY_UNWIND , None )
1898+ monitor .register_callback (DEBUGGER_ID , monitor .events .RAISE , None )
1899+ monitor .register_callback (DEBUGGER_ID , monitor .events .PY_UNWIND , None )
18791900
18801901 has_breaks = py_db .has_plugin_line_breaks
18811902 if not has_breaks :
0 commit comments