Index: pdb.py =================================================================== --- pdb.py (revision 78293) +++ pdb.py (working copy) @@ -13,8 +13,10 @@ import re import pprint import traceback +import signal + class Restart(Exception): """Causes a debugger to be restarted for the debugged python program.""" pass @@ -72,6 +74,8 @@ import readline except ImportError: pass + self.allow_kbdint = False + signal.signal(signal.SIGINT, self.sigint_handler) # Read $HOME/.pdbrc and ./.pdbrc self.rcLines = [] @@ -104,6 +108,13 @@ 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() + print >>self.stdout, "\nProgram interrupted. (Use 'cont' to resume)." + self.set_step() + self.set_trace(frame) + def reset(self): bdb.Bdb.reset(self) self.forget() @@ -176,7 +187,7 @@ 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 @@ -199,11 +210,22 @@ self.interaction(frame, exc_traceback) # General interaction function + def _cmdloop(self): + while 1: + try: + # keyboard interrupts allow for an easy way to interrupt + # the current command + self.allow_kbdint = True + self.cmdloop() + self.allow_kbdint = False + break + except KeyboardInterrupt: + print >>self.stdout, '--KeyboardInterrupt--' def interaction(self, frame, traceback): self.setup(frame, traceback) self.print_stack_entry(self.stack[self.curindex]) - self.cmdloop() + self._cmdloop() self.forget() def displayhook(self, obj): @@ -329,9 +351,22 @@ prompt_back = self.prompt self.prompt = '(com) ' self.commands_defining = True - self.cmdloop() - self.commands_defining = False - self.prompt = prompt_back + try: + self.cmdloop() + except (KeyboardInterrupt, IOError): + # It appears that that when pdb is reading input from a pipe + # we may get IOErrors, rather than KeyboardInterrupt. + # Now discard all the commands entered so far (essentially undo + # any effect of this "commands" cmd) + self.commands.pop(bnum) + self.commands_doprompt.pop(bnum) + self.commands_silent.pop(bnum) + # this will get caught by the _cmdloop and pdb will reenter + # the main command loop + raise KeyboardInterrupt() + finally: + self.commands_defining = False + self.prompt = prompt_back def do_break(self, arg, temporary = 0): # break [ ([filename:]lineno | function) [, "condition"] ]