diff --git a/src/prompt_toolkit/application/application.py b/src/prompt_toolkit/application/application.py index 726fc0a06..6a8043f46 100644 --- a/src/prompt_toolkit/application/application.py +++ b/src/prompt_toolkit/application/application.py @@ -17,6 +17,7 @@ sleep, ) from contextlib import ExitStack, contextmanager +from ctypes import c_int, c_void_p, pythonapi from subprocess import Popen from traceback import format_tb from typing import ( @@ -102,6 +103,21 @@ _SIGTSTP = getattr(signal, "SIGTSTP", None) +# The following functions are part of the stable ABI since python 3.2 +# See: https://docs.python.org/3/c-api/sys.html#c.PyOS_getsig + +# PyOS_sighandler_t PyOS_getsig(int i) +pythonapi.PyOS_getsig.restype = c_void_p +pythonapi.PyOS_getsig.argtypes = (c_int,) + +# PyOS_sighandler_t PyOS_setsig(int i, PyOS_sighandler_t h) +pythonapi.PyOS_setsig.restype = c_void_p +pythonapi.PyOS_setsig.argtypes = ( + c_int, + c_void_p, +) + + class Application(Generic[_AppResult]): """ The main Application class! @@ -807,6 +823,10 @@ def set_is_running() -> Iterator[None]: @contextmanager def set_handle_sigint(loop: AbstractEventLoop) -> Iterator[None]: if handle_sigint: + # save sigint handlers (python and os level) + # See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1576 + sigint = signal.getsignal(signal.SIGINT) + sigint_os = pythonapi.PyOS_getsig(signal.SIGINT) loop.add_signal_handler( signal.SIGINT, lambda *_: loop.call_soon_threadsafe( @@ -817,6 +837,8 @@ def set_handle_sigint(loop: AbstractEventLoop) -> Iterator[None]: yield finally: loop.remove_signal_handler(signal.SIGINT) + signal.signal(signal.SIGINT, sigint) + pythonapi.PyOS_setsig(signal.SIGINT, sigint_os) else: yield