diff options
author | Georg Brandl <georg@python.org> | 2010-12-04 16:00:47 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-12-04 16:00:47 (GMT) |
commit | 44f2b640ff0260f5e338e41ad3a2d13185396979 (patch) | |
tree | a448ea5dea9367826b6d7e325c1487395c704fe8 | |
parent | 1ed77f300b713166b0508eacd183c32f1d7437b2 (diff) | |
download | cpython-44f2b640ff0260f5e338e41ad3a2d13185396979.zip cpython-44f2b640ff0260f5e338e41ad3a2d13185396979.tar.gz cpython-44f2b640ff0260f5e338e41ad3a2d13185396979.tar.bz2 |
#7245: Add a SIGINT handler on continue in pdb that allows to break a program again by pressing Ctrl-C.
-rw-r--r-- | Doc/library/pdb.rst | 12 | ||||
-rw-r--r-- | Lib/bdb.py | 2 | ||||
-rwxr-xr-x | Lib/pdb.py | 37 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 47 insertions, 7 deletions
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index db21d1f..959fde1 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -135,7 +135,8 @@ The ``run_*`` functions and :func:`set_trace` are aliases for instantiating the :class:`Pdb` class and calling the method of the same name. If you want to access further features, you have to do this yourself: -.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None) +.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \ + nosigint=False) :class:`Pdb` is the debugger class. @@ -146,6 +147,11 @@ access further features, you have to do this yourself: patterns. The debugger will not step into frames that originate in a module that matches one of these patterns. [1]_ + By default, Pdb sets a handler for the SIGINT signal (which is sent when the + user presses Ctrl-C on the console) when you give a ``continue`` command. + This allows you to break into the debugger again by pressing Ctrl-C. If you + want Pdb not to touch the SIGINT handler, set *nosigint* tot true. + Example call to enable tracing with *skip*:: import pdb; pdb.Pdb(skip=['django.*']).set_trace() @@ -153,6 +159,10 @@ access further features, you have to do this yourself: .. versionadded:: 3.1 The *skip* argument. + .. versionadded:: 3.2 + The *nosigint* argument. Previously, a SIGINT handler was never set by + Pdb. + .. method:: run(statement, globals=None, locals=None) runeval(expression, globals=None, locals=None) runcall(function, *args, **kwds) @@ -214,7 +214,7 @@ class Bdb: def set_continue(self): # Don't stop except at breakpoints or when finished self._set_stopinfo(self.botframe, None, -1) - if not self.breaks: + if not self.breaks and not self.watching: # no breakpoints; run without debugger overhead sys.settrace(None) frame = sys._getframe().f_back @@ -66,14 +66,15 @@ Debugger commands # NOTE: the actual command documentation is collected from docstrings of the # commands and is appended to __doc__ after the class has been defined. +import os +import re import sys import cmd import bdb import dis -import os -import re import code import pprint +import signal import inspect import traceback import linecache @@ -133,7 +134,8 @@ line_prefix = '\n-> ' # Probably a better default class Pdb(bdb.Bdb, cmd.Cmd): - def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None): + def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, + nosigint=False): bdb.Bdb.__init__(self, skip=skip) cmd.Cmd.__init__(self, completekey, stdin, stdout) if stdout: @@ -148,6 +150,8 @@ class Pdb(bdb.Bdb, cmd.Cmd): import readline except ImportError: pass + self.allow_kbdint = False + self.nosigint = nosigint # Read $HOME/.pdbrc and ./.pdbrc self.rcLines = [] @@ -174,6 +178,15 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.commands_bnum = None # The breakpoint number for which we are # defining a list + def sigint_handler(self, signum, frame): + if self.allow_kbdint: + raise KeyboardInterrupt + self.message("\nProgram interrupted. (Use 'cont' to resume).") + self.set_step() + self.set_trace(frame) + # restore previous signal handler + signal.signal(signal.SIGINT, self._previous_sigint_handler) + def reset(self): bdb.Bdb.reset(self) self.forget() @@ -261,7 +274,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): if not self.commands_silent[currentbp]: self.print_stack_entry(self.stack[self.curindex]) if self.commands_doprompt[currentbp]: - self.cmdloop() + self._cmdloop() self.forget() return return 1 @@ -286,6 +299,17 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.interaction(frame, exc_traceback) # General interaction function + def _cmdloop(self): + while True: + try: + # keyboard interrupts allow for an easy way to cancel + # the current command, so allow them during interactive input + self.allow_kbdint = True + self.cmdloop() + self.allow_kbdint = False + break + except KeyboardInterrupt: + self.message('--KeyboardInterrupt--') def interaction(self, frame, traceback): if self.setup(frame, traceback): @@ -294,7 +318,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.forget() return self.print_stack_entry(self.stack[self.curindex]) - self.cmdloop() + self._cmdloop() self.forget() def displayhook(self, obj): @@ -909,6 +933,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): """c(ont(inue)) Continue execution, only stop when a breakpoint is encountered. """ + if not self.nosigint: + self._previous_sigint_handler = \ + signal.signal(signal.SIGINT, self.sigint_handler) self.set_continue() return 1 do_c = do_cont = do_continue @@ -49,6 +49,9 @@ Core and Builtins Library ------- +- Issue #7245: Add a SIGINT handler in pdb that allows to break a program + again after a "continue" command. + - Add the "interact" pdb command. - Issue #7905: Actually respect the keyencoding parameter to shelve.Shelf. |