diff --git i/Lib/bdb.py w/Lib/bdb.py index 59440a9..92994bf 100644 --- i/Lib/bdb.py +++ w/Lib/bdb.py @@ -25,6 +25,7 @@ class Bdb: self.breaks = {} self.fncache = {} self.frame_returning = None + self.botframe = None def canonic(self, filename): if filename == "<" + filename[1:-1] + ">": @@ -36,15 +37,16 @@ class Bdb: self.fncache[filename] = canonic return canonic - def reset(self): + def reset(self, botframe=None): import linecache linecache.checkcache() - self.botframe = None + self.botframe = botframe + self.quitting = False self._set_stopinfo(None, None) def trace_dispatch(self, frame, event, arg): - if self.quitting: - return # None + if not self.botframe: + self.botframe = frame if event == 'line': return self.dispatch_line(frame) if event == 'call': @@ -65,7 +67,9 @@ class Bdb: def dispatch_line(self, frame): if self.stop_here(frame) or self.break_here(frame): self.user_line(frame) - if self.quitting: raise BdbQuit + # Do not raise BdbQuit when debugging is started with set_trace + if self.quitting and self.botframe.f_back: + raise BdbQuit return self.trace_dispatch def dispatch_call(self, frame, arg): @@ -78,7 +82,8 @@ class Bdb: # No need to trace this function return # None self.user_call(frame, arg) - if self.quitting: raise BdbQuit + if self.quitting and self.botframe.f_back: + raise BdbQuit return self.trace_dispatch def dispatch_return(self, frame, arg): @@ -88,13 +93,15 @@ class Bdb: self.user_return(frame, arg) finally: self.frame_returning = None - if self.quitting: raise BdbQuit + if self.quitting and self.botframe.f_back: + raise BdbQuit return self.trace_dispatch def dispatch_exception(self, frame, arg): if self.stop_here(frame): self.user_exception(frame, arg) - if self.quitting: raise BdbQuit + if self.quitting and self.botframe.f_back: + raise BdbQuit return self.trace_dispatch # Normally derived classes don't override the following @@ -214,9 +221,14 @@ class Bdb: If frame is not specified, debugging starts from caller's frame. """ + # First disable tracing temporarily as set_trace() may be called while + # tracing is in use. For example when called from a signal handler and + # within a debugging session started with runcall(). + sys.settrace(None) + if frame is None: frame = sys._getframe().f_back - self.reset() + self.reset(botframe=self.botframe) while frame: frame.f_trace = self.trace_dispatch self.botframe = frame @@ -230,10 +242,6 @@ class Bdb: if not self.breaks: # no breakpoints; run without debugger overhead sys.settrace(None) - frame = sys._getframe().f_back - while frame and frame is not self.botframe: - del frame.f_trace - frame = frame.f_back def set_quit(self): self.stopframe = self.botframe @@ -401,7 +409,6 @@ class Bdb: except BdbQuit: pass finally: - self.quitting = 1 sys.settrace(None) def runeval(self, expr, globals=None, locals=None): @@ -419,7 +426,6 @@ class Bdb: except BdbQuit: pass finally: - self.quitting = 1 sys.settrace(None) def runctx(self, cmd, globals, locals): @@ -437,7 +443,6 @@ class Bdb: except BdbQuit: pass finally: - self.quitting = 1 sys.settrace(None) return res diff --git i/Lib/pdb.py w/Lib/pdb.py index 5468d3f..51a6ea9 100755 --- i/Lib/pdb.py +++ w/Lib/pdb.py @@ -104,8 +104,8 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.commands_bnum = None # The breakpoint number for which we are # defining a list - def reset(self): - bdb.Bdb.reset(self) + def reset(self, botframe=None): + bdb.Bdb.reset(self, botframe) self.forget() def forget(self):