-
Notifications
You must be signed in to change notification settings - Fork 716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recent SIGINT change breaks ipython / cysignals -- affects sagemath #1576
Comments
This could be fixed by making BTW, the argument Anyway my patch to change the default for --- a/prompt_toolkit/application/application.py 2022-02-11 05:06:37.000000000 -0300
+++ b/prompt_toolkit/application/application.py 2022-02-21 10:43:13.828058001 -0300
@@ -634,7 +634,7 @@
self,
pre_run: Optional[Callable[[], None]] = None,
set_exception_handler: bool = True,
- handle_sigint: bool = True,
+ handle_sigint: bool = False,
slow_callback_duration: float = 0.5,
) -> _AppResult:
"""
@@ -859,7 +859,7 @@
self,
pre_run: Optional[Callable[[], None]] = None,
set_exception_handler: bool = True,
- handle_sigint: bool = True,
+ handle_sigint: bool = False,
in_thread: bool = False,
) -> _AppResult:
""" With this patch added to 3.0.28 everything seems to be back to normal, including handling of Ctrl-C in sagemath. |
The root cause of this issue is that calling A possible solution to this is to save the sigint handler before It is not enough to use The patch below does precisely this. To avoid a hard dependency on I'd appreciate any comments about this proposal. This issue breaks sagemath in a very annoying way -- the only alternative is to hold prompt_toolkit to 3.0.24 (void linux is currently shipping 3.0.28 and we are wary of patching prompt_toolkit without some feedback from upstream, cf void-linux/void-packages#35730 (comment)). BTW, I realized that the issue affecting xonsh (for which #1538 was introduced) also affects ipython: sending SIGINT to ipython with prompt_toolkit 3.0.24 will crash ipython but with prompt_toolkit 3.0.28 is ok, so keeping it enabled + the patch below is indeed an improvement. --- a/prompt_toolkit/application/application.py 2022-02-11 05:06:37.000000000 -0300
+++ b/prompt_toolkit/application/application.py 2022-02-22 15:31:02.248681343 -0300
@@ -98,6 +98,10 @@
except ImportError:
import prompt_toolkit.eventloop.dummy_contextvars as contextvars # type: ignore
+try:
+ from cysignals import pysignals
+except ImportError:
+ from . import dummy_pysignals as pysignals
__all__ = [
"Application",
@@ -805,6 +809,9 @@
loop = get_event_loop()
if handle_sigint:
+ # save sigint handlers
+ _sigint = signal.getsignal(signal.SIGINT)
+ _sigint_os = pysignals.getossignal(signal.SIGINT)
loop.add_signal_handler(
signal.SIGINT,
lambda *_: loop.call_soon_threadsafe(
@@ -843,6 +850,8 @@
if handle_sigint:
loop.remove_signal_handler(signal.SIGINT)
+ # restore python and os-level signal handlers
+ pysignals.setsignal(signal.SIGINT, _sigint, _sigint_os)
# Reset slow_callback_duration.
loop.slow_callback_duration = original_slow_callback_duration
--- a/prompt_toolkit/application/dummy_pysignals.py 1969-12-31 21:00:00.000000000 -0300
+++ b/prompt_toolkit/application/dummy_pysignals.py 2022-02-22 15:31:26.432386296 -0300
@@ -0,0 +1,10 @@
+# fallback in case cysignals is not available
+# these functions don't save the os level handlers
+
+import signal
+
+def getossignal(sig):
+ return None
+
+def setsignal(sig, action, osaction=None):
+ return signal.signal(sig, action) |
Hi @tornaria, Thanks for the feedback, and sorry for the delay.
When you say "because the whole point is to be able to break extension code which may not run python's handlers for a long time", does it mean that this can break out of literally any extension code and have an exception propagate? How do you know whether or not this extension holds a lock somewhere? Would this not cause any deadlocks at some point, due to code trying to acquire a lock that was not released earlier to due this signal handling? |
Now that ipython requires prompt-toolkit >= 3.0.30, this workaround is no longer feasible. |
@jonathanslenders With @tornaria's patch, there wouldn't be a dependency on |
Would you feel more comfortable if I try to implement the same using The only thing needed here is that the
This is not automatic: signals only work between matching calls to |
@jonathanslenders : Here's a new proposal that uses --- a/src/prompt_toolkit/application/application.py
+++ b/src/prompt_toolkit/application/application.py
@@ -17,6 +17,7 @@ from asyncio import (
sleep,
)
from contextlib import ExitStack, contextmanager
+from ctypes import pythonapi, c_int, c_void_p
from subprocess import Popen
from traceback import format_tb
from typing import (
@@ -100,6 +101,18 @@ _SIGWINCH = getattr(signal, "SIGWINCH", None)
_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!
@@ -794,6 +807,10 @@ class Application(Generic[_AppResult]):
@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(
@@ -804,6 +821,8 @@ class Application(Generic[_AppResult]):
yield
finally:
loop.remove_signal_handler(signal.SIGINT)
+ signal.signal(signal.SIGINT, sigint)
+ pythonapi.PyOS_setsig(signal.SIGINT, sigint_os)
else:
yield
|
And here is how to reproduce the issue in ipython, without any reference to sagemath or cysignals. The example below installs a custom sigint handler, runs an infinite loop, and then send ^C.
|
Starting with 3.0.25 (i.e. after #1538) hitting control-C is not working properly in sagemath.
Background: sagemath uses cysignals so that signals can be handled when running extension code; cysignals installs a custom signal handler to catch signals while running extension code. When a signal is received, it unwinds and raises a python exception. This is used extensively in sagemath.
The issue is not tied with sagemath and can be easily reproduced from ipython as follows:
EXAMPLE
forever.pyx
:After this you'll have an extension module, in my system the file is named
forever.cpython-310-x86_64-linux-gnu.so
.SIGINT
from another process also doesn't work.The text was updated successfully, but these errors were encountered: