This is a minimal reproducible example of a bug using a typical interrupt handler so that files being written to are not corrupted. Running the script as python filename.py
works as intended, but the issue occurs on running this script as sage filename.sage
or as python filename.py
with any Sage import statement similar to from sage.all import matrix
.
As commented, the first time.sleep(3)
can be interrupted correctly, the second time.sleep(4)
correctly raises the KeyboardInterrupt()
on exiting the scope of with DelayedKeyboardInterrupt()
, but the final time.sleep(5)
call cannot be interrupted, but the hardcoded KeyboardInterrupt()
at the end still works. Printing signal.getsignal(signal.SIGINT)
shows that DelayedKeyboardInterrupt()
correctly restores the handler.
I realise that cysignals
is preferred with Sage, but cannot figure out how to without major changes.
import signal
import time
class DelayedKeyboardInterrupt:
def __enter__(self):
self.sigint_handler = signal.signal(signal.SIGINT, self.handler)
self.signal_received = False
def handler(self, sig, frame):
self.signal_received = True
print("Delaying exit for file I/O.")
def __exit__(self, type, value, traceback):
signal.signal(signal.SIGINT, self.sigint_handler)
if self.signal_received:
raise KeyboardInterrupt("delayed")
print("sleeping unprotected for 3 sec")
time.sleep(3) # Ctrl+C here raises KeyboardInterrupt instantly
with DelayedKeyboardInterrupt():
print("sleeping protected for 4 sec")
time.sleep(4) # Ctrl+C here raises KeyboardInterrupt("delayed") after end of 4 sec
print("sleeping 'unprotected' for 5 sec")
time.sleep(5) # Ctrl+C here does not raise any KeyboardInterrupt
raise KeyboardInterrupt("hardcoded") # this raises correctly