]> granicus.if.org Git - python/commitdiff
#7245: Add a SIGINT handler on continue in pdb that allows to break a program again...
authorGeorg Brandl <georg@python.org>
Sat, 4 Dec 2010 16:00:47 +0000 (16:00 +0000)
committerGeorg Brandl <georg@python.org>
Sat, 4 Dec 2010 16:00:47 +0000 (16:00 +0000)
Doc/library/pdb.rst
Lib/bdb.py
Lib/pdb.py
Misc/NEWS

index db21d1f7c7c2233d369a4ddfa1cd46d0fc8f103f..959fde1b40e374a275a29589f3a50656f3a92da1 100644 (file)
@@ -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)
index 9f5e7ae630d0d310b13acb3e46f7568ae35455a1..08dce8f2f9f0e44a33bc74fb38562af8d267f303 100644 (file)
@@ -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
index d6a9a925da017bd74711c045144ff72d4b55e6d0..ac53eba135c32176ff88557b31e8f56d6a6c358a 100755 (executable)
@@ -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
index c5a525f5a72e65d80ad52333b70022a00a7bd7e1..a741d6e5880c208499d5c6cec4b9458738018eba 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.