-
-
Notifications
You must be signed in to change notification settings - Fork 656
Explicitly check signum in GAP error handler #40727
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
base: develop
Are you sure you want to change the base?
Conversation
Documentation preview for this PR (built with commit 4010185; changes) is ready! 🎉 |
I don't understand the remark about wasting memory in exceptional case however. |
The old version was constructing two exception objects in global scope (so, effectively, when sage starts) and then never destroying them. It's irrelevant now. |
I started poking at the memory usage because I was confused about why import gc
import psutil
from sage.doctest.util import ensure_interruptible_after
def vmem_used_in_mib():
return psutil.virtual_memory().used / 1024.0**2
a, b = libgap.GL(1000, 3).GeneratorsOfGroup()
g = a * b
e = libgap(2 ^ 400000)
print(f"vmem used before: {vmem_used_in_mib()}")
for _ in range(5000):
with ensure_interruptible_after(0.1, max_wait_after_interrupt=5):
g^e
gc.collect()
print(f"vmem used after: {vmem_used_in_mib()}") And running it, I get output like:
(The "used" memory reported by psutil is nonsense, but you can still wonder why it grows in some cases and does not grow in others. The OS shouldn't need to allocate more memory ad infinitum if each loop iteration cleans up after itself.) |
I think the logic is cleaner without the special case for the if last_signum == SIGINT:
exc_type = <PyObject*>KeyboardInterrupt
exc_val_python = KeyboardInterrupt()
exc_val = <PyObject*>exc_val_python
elif last_signum == SIGALRM:
from cysignals.signals import AlarmInterrupt
exc_type = <PyObject*>AlarmInterrupt
exc_val_python = AlarmInterrupt()
exc_val = <PyObject*>exc_val_python
else:
exc_type = <PyObject*>GAPError
exc_val = <PyObject*>msg
last_signum = 0 (it doesn't hurt to set |
maybe it's just because gap itself leaks memory? |
The It occurred to me that you could even keep the "this should never happen" message in the example I gave: else:
if not last_signum:
msg = "..."
exc_type = <PyObject*>GAPError
exc_val = <PyObject*>msg so the trade-off is between duplicating that "else" block, and setting |
about PyErr_Restore taking a string, I have no idea either, but the previous code does that as well, and there are some remarks scattered online that if PyErr_SetString is used then PyErr_Fetch returns a string, and from the documentation we know that PyErr_Restore ought to be able to take what PyErr_Fetch returns. |
Follow-up to #40613.
Instead of checking for the string
user interrupt
(which might change between GAP versions, or if there's some unforeseen way the string might be sneaked in), we store the signum from the signal handler then check it in the GAP error handler.Also optionally use
AlarmInterrupt
instead ofKeyboardInterrupt
if cysignals is available.📝 Checklist
⌛ Dependencies