Browse files

inputhook_qt4: handle KeyboardInterrupt in a way compatible with 'rea…


While the previous code works fine on Windows, on Linux with
'readline' the situation is different: once we disable the Qt4 event
loop, we go back waiting in the select() inside readline.c's
readline_until_enter_or_signal() function. When that select() is
interrupted, the PyOS_InputHook is executed if present and the pending
KeyboardInterrupt is delivered as soon as bytecode execution starts,
even before entering the `try:` clause! As at that point we're in a
ctypes callback, this will lead to an internal error. The only
solution is therefore to disable the PyOS_InputHook temporarily.
  • Loading branch information...
1 parent 6ab38c6 commit fa663483c20e8d97f1296817371abac53015217b @cboos committed Oct 9, 2011
Showing with 11 additions and 12 deletions.
  1. +11 −12 IPython/lib/
@@ -208,23 +208,16 @@ def enable_qt4(self, app=None):
# #481).
# Note that we can't let KeyboardInterrupt escape from that
- # hook, (no exception can't be raised from within a ctypes
- # python callback). We need to make a compromise: a trapped
- # KeyboardInterrupt will prevent the input hook to re-enter
- # the exec loop, until we start over with a new prompt line.
- # This means one needs a double CTRL+C to get back to the
- # prompt.
+ # hook, as no exception can be raised from within a ctypes
+ # python callback. We need to make a compromise: a trapped
+ # KeyboardInterrupt will temporarily disable the input hook
+ # until we start over with a new prompt line with a second
+ # CTRL+C.
got_kbdint = [False]
- def preprompthook_qt4(self):
- got_kbdint[0] = False
- ipapi.get().set_hook('pre_prompt_hook', preprompthook_qt4)
def inputhook_qt4():
- if got_kbdint[0]:
- return 0
app.processEvents(QtCore.QEventLoop.AllEvents, 300)
if not stdin_ready():
timer = QtCore.QTimer()
@@ -235,11 +228,17 @@ def inputhook_qt4():
except KeyboardInterrupt:
got_kbdint[0] = True
+ self.clear_inputhook()
print("\n(event loop interrupted - "
"hit CTRL+C again to clear the prompt)")
return 0
+ def preprompthook_qt4(ishell):
+ if got_kbdint[0]:
+ self.set_inputhook(inputhook_qt4)
+ ipapi.get().set_hook('pre_prompt_hook', preprompthook_qt4)
self._current_gui = GUI_QT4
app._in_event_loop = True
self._apps[GUI_QT4] = app

0 comments on commit fa66348

Please sign in to comment.