Repository: ipython/ipython

Issue:
Zmq errors appearing with `Ctrl-C` in console/qtconsole
When using either the qt or terminal consoles (both zmq-based), if we try to interrupt an ipdb session with `Ctrl-C`, a zmq error propagates all the way to the user:

```
ipdb> ---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-2-51af4340c641> in <module>()
----> 1 get_ipython().magic(u'debug ')

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in magic(self, arg_s)
   2158         magic_name, _, magic_arg_s = arg_s.partition(' ')
   2159         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2160         return self.run_line_magic(magic_name, magic_arg_s)
   2161 
   2162     #-------------------------------------------------------------------------

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in run_line_magic(self, magic_name, line)
   2079                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2080             with self.builtin_trap:
-> 2081                 result = fn(*args,**kwargs)
   2082             return result
   2083 

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/magics/execution.pyc in debug(self, line, cell)

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/magic.pyc in <lambda>(f, *a, **k)
    189     # but it's overkill for just that one bit of state.
    190     def magic_deco(arg):
--> 191         call = lambda f, *a, **k: f(*a, **k)
    192 
    193         if callable(arg):

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/magics/execution.pyc in debug(self, line, cell)
    331 
    332         if not (args.breakpoint or args.statement or cell):
--> 333             self._debug_post_mortem()
    334         else:
    335             code = "\n".join(args.statement)

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/magics/execution.pyc in _debug_post_mortem(self)
    339 
    340     def _debug_post_mortem(self):
--> 341         self.shell.debugger(force=True)
    342 
    343     def _debug_exec(self, code, breakpoint):

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in debugger(self, force)
    920 
    921         with self.readline_no_record:
--> 922             pm()
    923 
    924     #-------------------------------------------------------------------------

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in <lambda>()
    917         else:
    918             # fallback to our internal debugger
--> 919             pm = lambda : self.InteractiveTB.debugger(force=True)
    920 
    921         with self.readline_no_record:

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/ultratb.pyc in debugger(self, force)
   1007                     etb = etb.tb_next
   1008                 self.pdb.botframe = etb.tb_frame
-> 1009                 self.pdb.interaction(self.tb.tb_frame, self.tb)
   1010 
   1011         if hasattr(self,'tb'):

/home/fperez/usr/lib/python2.7/site-packages/IPython/core/debugger.pyc in interaction(self, frame, traceback)
    264     def interaction(self, frame, traceback):
    265         self.shell.set_completer_frame(frame)
--> 266         OldPdb.interaction(self, frame, traceback)
    267 
    268     def new_do_up(self, arg):

/usr/lib/python2.7/pdb.pyc in interaction(self, frame, traceback)
    208         self.setup(frame, traceback)
    209         self.print_stack_entry(self.stack[self.curindex])
--> 210         self.cmdloop()
    211         self.forget()
    212 

/usr/lib/python2.7/cmd.pyc in cmdloop(self, intro)
    128                     if self.use_rawinput:
    129                         try:
--> 130                             line = raw_input(self.prompt)
    131                         except EOFError:
    132                             line = 'EOF'

/home/fperez/usr/lib/python2.7/site-packages/IPython/kernel/zmq/ipkernel.pyc in <lambda>(prompt)
    352         # raw_input in the user namespace.
    353         if content.get('allow_stdin', False):
--> 354             raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
    355         else:
    356             raw_input = lambda prompt='' : self._no_raw_input()

/home/fperez/usr/lib/python2.7/site-packages/IPython/kernel/zmq/ipkernel.pyc in _raw_input(self, prompt, ident, parent)
    764         while True:
    765             try:
--> 766                 ident, reply = self.session.recv(self.stdin_socket, 0)
    767             except Exception:
    768                 self.log.warn("Invalid Message:", exc_info=True)

/home/fperez/usr/lib/python2.7/site-packages/IPython/kernel/zmq/session.pyc in recv(self, socket, mode, content, copy)
    655             socket = socket.socket
    656         try:
--> 657             msg_list = socket.recv_multipart(mode, copy=copy)
    658         except zmq.ZMQError as e:
    659             if e.errno == zmq.EAGAIN:

/usr/lib/python2.7/dist-packages/zmq/core/pysocket.pyc in recv_multipart(self, flags, copy, track)
    208 
    209     """
--> 210     parts = [self.recv(flags, copy=copy, track=track)]
    211     # have first part already, only loop while more to receive
    212     while self.getsockopt(zmq.RCVMORE):

/usr/lib/python2.7/dist-packages/zmq/core/socket.so in zmq.core.socket.Socket.recv (zmq/core/socket.c:5643)()

/usr/lib/python2.7/dist-packages/zmq/core/socket.so in zmq.core.socket.Socket.recv (zmq/core/socket.c:5465)()

/usr/lib/python2.7/dist-packages/zmq/core/socket.so in zmq.core.socket._recv_copy (zmq/core/socket.c:1688)()

/usr/lib/python2.7/dist-packages/zmq/core/error.so in zmq.core.error.ZMQError.__init__ (zmq/core/error.c:1059)()

KeyboardInterrupt: 
```



Discussion:
That's not a zmq error, that's a KeyboardInterrupt.  I guess you mean we should hide tracebacks on KeyboardInterrupt?

in raw_input, that is.  Probably makes sense.

yes, sorry, that's what I should have said... We shouldn't be dumping internal machinery tracebacks inside raw_input if the only error is a KBINT.

too tired to think, I guess :)


Resolving patch:
diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py
--- a/IPython/core/debugger.py
+++ b/IPython/core/debugger.py
@@ -263,7 +263,13 @@ def set_colors(self, scheme):
 
     def interaction(self, frame, traceback):
         self.shell.set_completer_frame(frame)
-        OldPdb.interaction(self, frame, traceback)
+        while True:
+            try:
+                OldPdb.interaction(self, frame, traceback)
+            except KeyboardInterrupt:
+                self.shell.write("\nKeyboardInterrupt\n")
+            else:
+                break
 
     def new_do_up(self, arg):
         OldPdb.do_up(self, arg)
diff --git a/IPython/kernel/zmq/ipkernel.py b/IPython/kernel/zmq/ipkernel.py
--- a/IPython/kernel/zmq/ipkernel.py
+++ b/IPython/kernel/zmq/ipkernel.py
@@ -766,6 +766,9 @@ def _raw_input(self, prompt, ident, parent):
                 ident, reply = self.session.recv(self.stdin_socket, 0)
             except Exception:
                 self.log.warn("Invalid Message:", exc_info=True)
+            except KeyboardInterrupt:
+                # re-raise KeyboardInterrupt, to truncate traceback
+                raise KeyboardInterrupt
             else:
                 break
         try:


Test patch: