diff --git a/IPython/lib/inputhook.py b/IPython/lib/inputhook.py index e60d238..7e9b954 100644 --- a/IPython/lib/inputhook.py +++ b/IPython/lib/inputhook.py @@ -51,14 +51,38 @@ def _stdin_ready_other(): """Return True, assuming there's something to read on stdin.""" return True # + +def _ignore_CTRL_C_posix(): + """Ignore CTRL+C (SIGINT).""" + signal.signal(signal.SIGINT, signal.SIG_IGN) + +def _allow_CTRL_C_posix(): + """Take CTRL+C into account (SIGINT).""" + signal.signal(signal.SIGINT, signal.default_int_handler) + +def _ignore_CTRL_C_other(): + """Ignore CTRL+C (not implemented).""" + pass + +def _allow_CTRL_C_other(): + """Take CTRL+C into account (not implemented).""" + pass + if os.name == 'posix': import select + import signal stdin_ready = _stdin_ready_posix + ignore_CTRL_C = _ignore_CTRL_C_posix + allow_CTRL_C = _allow_CTRL_C_posix elif os.name == 'nt': import msvcrt stdin_ready = _stdin_ready_nt + ignore_CTRL_C = _ignore_CTRL_C_other + allow_CTRL_C = _allow_CTRL_C_other else: stdin_ready = _stdin_ready_other + ignore_CTRL_C = _ignore_CTRL_C_other + allow_CTRL_C = _allow_CTRL_C_other #----------------------------------------------------------------------------- @@ -94,6 +118,11 @@ class InputHookManager(object): def set_inputhook(self, callback): """Set PyOS_InputHook to callback and return the previous one.""" + # On platforms with 'readline' support, it's all too likely to + # have a KeyboardInterrupt signal delivered *even before* an + # initial ``try:`` clause in the callback can be executed, so + # we need to disable CTRL+C in this situation. + ignore_CTRL_C() self._callback = callback self._callback_pyfunctype = self.PYFUNC(callback) pyos_inputhook_ptr = self.get_pyos_inputhook() @@ -117,6 +146,7 @@ class InputHookManager(object): pyos_inputhook_ptr = self.get_pyos_inputhook() original = self.get_pyos_inputhook_as_func() pyos_inputhook_ptr.value = ctypes.c_void_p(None).value + allow_CTRL_C() self._reset() return original diff --git a/IPython/lib/inputhookqt4.py b/IPython/lib/inputhookqt4.py index 5e896a6..128bf9c 100644 --- a/IPython/lib/inputhookqt4.py +++ b/IPython/lib/inputhookqt4.py @@ -17,7 +17,7 @@ Author: Christian Boos #----------------------------------------------------------------------------- from IPython.external.qt_for_kernel import QtCore, QtGui -from IPython.lib.inputhook import stdin_ready +from IPython.lib.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready #----------------------------------------------------------------------------- # Code @@ -78,6 +78,7 @@ def create_inputhook_qt4(mgr, app=None): back to a clean prompt line. """ try: + allow_CTRL_C() app = QtCore.QCoreApplication.instance() app.processEvents(QtCore.QEventLoop.AllEvents, 300) if not stdin_ready(): @@ -88,13 +89,14 @@ def create_inputhook_qt4(mgr, app=None): app.exec_() timer.stop() except KeyboardInterrupt: + ignore_CTRL_C() got_kbdint[0] = True - mgr.clear_inputhook() print("\nKeyboardInterrupt - qt4 event loop interrupted!" "\n * hit CTRL+C again to clear the prompt" "\n * use '%gui none' to disable the event loop" " permanently" "\n and '%gui qt4' to re-enable it later") + mgr.clear_inputhook() return 0 def preprompthook_qt4(ishell):