You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
while ensuring the plot is displayed, do the following
plt.pause(3)
↓
wait for it to finish, then
sleep(10)
try to ctrl-C it, it won't work.
The reason is the following. Cysignals contains
# Set the Python-level interrupt handler. When a SIGINT occurs,
# this will not be called directly. Instead, a SIGINT is caught by
# our interrupt handler, set up in implementation.c. If it happens
# during pure Python code (not within sig_on()/sig_off()), the
# handler will set Python's interrupt flag. Python regularly checks
# this and will call its interrupt handler (which is the one we set
# now). This handler issues a sig_check() which finally raises the
# KeyboardInterrupt exception.
import signal
old = signal.signal(signal.SIGINT, python_check_interrupt)
setup_alt_stack()
setup_cysignals_handlers()
In other words, python_check_interrupt is set to be the Python-level signal handler, however then the actual signal handler is something set in C
/* Install signal handlers */
/* Handlers for interrupt-like signals */
sa.sa_handler = cysigs_interrupt_handler;
sa.sa_flags = 0;
#ifdef SIGHUP
if (sigaction(SIGHUP, &sa, NULL)) {perror("cysignals sigaction"); exit(1);}
#endif
if (sigaction(SIGINT, &sa, NULL)) {perror("cysignals sigaction"); exit(1);}
#ifdef SIGALRM
if (sigaction(SIGALRM, &sa, NULL)) {perror("cysignals sigaction"); exit(1);}
#endif
that causes a problem, because matplotlib temporarily sets the signal handler to its own then revert it later. Equivalently the following also breaks ctrl-C even though it should be a no-op:
import signal
from signal import SIGINT
signal.signal(SIGINT, signal.getsignal(SIGINT))
the function returned is Python function python_check_interrupt.
After signal.signal(SIGINT, signal.getsignal(SIGINT)) (which is supposed to be a no-op), now on ctrl-C, only python_check_interrupt is called without actually setting the value of interrupt_received:
/* Handler for SIGHUP, SIGINT, SIGALRM, SIGTERM
*
* Inside sig_on() (i.e. when cysigs.sig_on_count is positive), this
* raises an exception and jumps back to sig_on().
* Outside of sig_on(), we set Python's interrupt flag using
* PyErr_SetInterrupt() */
static void cysigs_interrupt_handler(int sig)
{
[…]
cysigs.interrupt_received = sig;
custom_set_pending_signal(sig);
Relevant explanation:
# Set the Python-level interrupt handler. When a SIGINT occurs,
# this will not be called directly. Instead, a SIGINT is caught by
# our interrupt handler, set up in implementation.c. If it happens
# during pure Python code (not within sig_on()/sig_off()), the
# handler will set Python's interrupt flag. Python regularly checks
# this and will call its interrupt handler (which is the one we set
# now). This handler issues a sig_check() which finally raises the
# KeyboardInterrupt exception.
import signal
old = signal.signal(signal.SIGINT, python_check_interrupt)
tl;dr the Python-level interrupt handler actually need to set the signal, as the fallback. Probably.
Some investigation: there is this thing
def init_cysignals():
"""
Initialize ``cysignals``.
This is normally done exactly once, namely when importing
``cysignals``. However, it is legal to call this multiple times,
for example when switching between the ``cysignals`` interrupt
handler and a different interrupt handler.
OUTPUT: the old Python-level interrupt handler
I think a workaround for now is just to call that function again.
The text was updated successfully, but these errors were encountered:
After plt.pause() is called, ctrl-C stops working (outside plt.pause() itself).
To reproduce:
↓
↓
while ensuring the plot is displayed, do the following
↓
wait for it to finish, then
try to ctrl-C it, it won't work.
The reason is the following. Cysignals contains
In other words,
python_check_interrupt
is set to be the Python-level signal handler, however then the actual signal handler is something set in Cthat causes a problem, because matplotlib temporarily sets the signal handler to its own then revert it later. Equivalently the following also breaks ctrl-C even though it should be a no-op:
the function returned is Python function
python_check_interrupt
.After
signal.signal(SIGINT, signal.getsignal(SIGINT))
(which is supposed to be a no-op), now on ctrl-C, onlypython_check_interrupt
is called without actually setting the value ofinterrupt_received
:Relevant explanation:
tl;dr the Python-level interrupt handler actually need to set the signal, as the fallback. Probably.
Some investigation: there is this thing
I think a workaround for now is just to call that function again.
The text was updated successfully, but these errors were encountered: