#7245: Add a SIGINT handler on continue in pdb that allows to break a program again by pressing Ctrl-C.
This commit is contained in:
parent
1ed77f300b
commit
44f2b640ff
|
@ -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
|
||||
|
|
37
Lib/pdb.py
37
Lib/pdb.py
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue