|
17 | 17 | sleep, |
18 | 18 | ) |
19 | 19 | from contextlib import ExitStack, contextmanager |
20 | | -from ctypes import c_int, c_void_p, pythonapi |
21 | 20 | from subprocess import Popen |
22 | 21 | from traceback import format_tb |
23 | 22 | from typing import ( |
|
103 | 102 | _SIGTSTP = getattr(signal, "SIGTSTP", None) |
104 | 103 |
|
105 | 104 |
|
106 | | -# The following functions are part of the stable ABI since python 3.2 |
107 | | -# See: https://docs.python.org/3/c-api/sys.html#c.PyOS_getsig |
108 | | - |
109 | | -# PyOS_sighandler_t PyOS_getsig(int i) |
110 | | -pythonapi.PyOS_getsig.restype = c_void_p |
111 | | -pythonapi.PyOS_getsig.argtypes = (c_int,) |
112 | | - |
113 | | -# PyOS_sighandler_t PyOS_setsig(int i, PyOS_sighandler_t h) |
114 | | -pythonapi.PyOS_setsig.restype = c_void_p |
115 | | -pythonapi.PyOS_setsig.argtypes = ( |
116 | | - c_int, |
117 | | - c_void_p, |
118 | | -) |
119 | | - |
120 | | - |
121 | 105 | class Application(Generic[_AppResult]): |
122 | 106 | """ |
123 | 107 | The main Application class! |
@@ -823,22 +807,19 @@ def set_is_running() -> Iterator[None]: |
823 | 807 | @contextmanager |
824 | 808 | def set_handle_sigint(loop: AbstractEventLoop) -> Iterator[None]: |
825 | 809 | if handle_sigint: |
826 | | - # save sigint handlers (python and os level) |
827 | | - # See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1576 |
828 | | - sigint = signal.getsignal(signal.SIGINT) |
829 | | - sigint_os = pythonapi.PyOS_getsig(signal.SIGINT) |
830 | | - loop.add_signal_handler( |
831 | | - signal.SIGINT, |
832 | | - lambda *_: loop.call_soon_threadsafe( |
833 | | - self.key_processor.send_sigint |
834 | | - ), |
835 | | - ) |
836 | | - try: |
837 | | - yield |
838 | | - finally: |
839 | | - loop.remove_signal_handler(signal.SIGINT) |
840 | | - signal.signal(signal.SIGINT, sigint) |
841 | | - pythonapi.PyOS_setsig(signal.SIGINT, sigint_os) |
| 810 | + with _restore_sigint_from_ctypes(): |
| 811 | + # save sigint handlers (python and os level) |
| 812 | + # See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1576 |
| 813 | + loop.add_signal_handler( |
| 814 | + signal.SIGINT, |
| 815 | + lambda *_: loop.call_soon_threadsafe( |
| 816 | + self.key_processor.send_sigint |
| 817 | + ), |
| 818 | + ) |
| 819 | + try: |
| 820 | + yield |
| 821 | + finally: |
| 822 | + loop.remove_signal_handler(signal.SIGINT) |
842 | 823 | else: |
843 | 824 | yield |
844 | 825 |
|
@@ -1609,3 +1590,36 @@ def attach_winch_signal_handler( |
1609 | 1590 | previous_winch_handler._callback, |
1610 | 1591 | *previous_winch_handler._args, |
1611 | 1592 | ) |
| 1593 | + |
| 1594 | + |
| 1595 | +@contextmanager |
| 1596 | +def _restore_sigint_from_ctypes() -> Generator[None, None, None]: |
| 1597 | + # The following functions are part of the stable ABI since python 3.2 |
| 1598 | + # See: https://docs.python.org/3/c-api/sys.html#c.PyOS_getsig |
| 1599 | + # Inline import: these are not available on Pypy. |
| 1600 | + try: |
| 1601 | + from ctypes import c_int, c_void_p, pythonapi |
| 1602 | + except ImportError: |
| 1603 | + # Any of the above imports don't exist? Don't do anything here. |
| 1604 | + yield |
| 1605 | + return |
| 1606 | + |
| 1607 | + # PyOS_sighandler_t PyOS_getsig(int i) |
| 1608 | + pythonapi.PyOS_getsig.restype = c_void_p |
| 1609 | + pythonapi.PyOS_getsig.argtypes = (c_int,) |
| 1610 | + |
| 1611 | + # PyOS_sighandler_t PyOS_setsig(int i, PyOS_sighandler_t h) |
| 1612 | + pythonapi.PyOS_setsig.restype = c_void_p |
| 1613 | + pythonapi.PyOS_setsig.argtypes = ( |
| 1614 | + c_int, |
| 1615 | + c_void_p, |
| 1616 | + ) |
| 1617 | + |
| 1618 | + sigint = signal.getsignal(signal.SIGINT) |
| 1619 | + sigint_os = pythonapi.PyOS_getsig(signal.SIGINT) |
| 1620 | + |
| 1621 | + try: |
| 1622 | + yield |
| 1623 | + finally: |
| 1624 | + signal.signal(signal.SIGINT, sigint) |
| 1625 | + pythonapi.PyOS_setsig(signal.SIGINT, sigint_os) |
0 commit comments