-
-
Notifications
You must be signed in to change notification settings - Fork 561
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
Make MonoDictEraser
and TripleDictEraser
safe against "recursion depth exceeded"
#15069
Comments
comment:1
Comments 97--102 at #10963 provide some ideas how to solve the problem. Actually I originally thought that the solution is easy: When the eraser of a Inserting print statements shows that in unpatched Sage the eraser calls are nested, which explains the "recursion depth exceeded". And in fact, the trick with the temporary variable has the effect that the eraser calls are now neatly ordered and not nested. And now comes the punch-line: The "recursion depth exceeded" error does not vanish!!! The comments at #10963 seem to show that the error behaves different if the class A in the example from the ticket description is a Python or a Cython class. But there is a recursion depth problem in either case. |
comment:2
Defining
and keeping track of the order in which the elements are created by
I see that the n-th element created (the first one is |
comment:3
Replying to @simon-king-jena:
Or not? The weakref module says: Weak references to an object are cleared before the object's Hm. I understand that |
comment:4
It seems that it is not enough to keep a reference to the value of the key-value pair being deleted by the eraser---but if the eraser returns the value, then I see the recursion depth error disappear. Hence, with this patch diff --git a/sage/structure/coerce_dict.pyx b/sage/structure/coerce_dict.pyx
--- a/sage/structure/coerce_dict.pyx
+++ b/sage/structure/coerce_dict.pyx
@@ -187,14 +187,17 @@
h,offset = r.key
cdef list bucket = <object>PyList_GET_ITEM(buckets, (<size_t>h) % PyList_GET_SIZE(buckets))
cdef Py_ssize_t i
+ cdef object val
for i from 0 <= i < PyList_GET_SIZE(bucket) by 3:
if PyInt_AsSsize_t(PyList_GET_ITEM(bucket,i))==h:
if PyList_GET_ITEM(bucket,i+offset)==<void *>r:
+ val = <object>PyList_GET_ITEM(bucket,i+2)
del bucket[i:i+3]
D._size -= 1
break
else:
break
+ return val
seems to work. Doing tests now... |
Author: Simon King |
comment:5
Attachment: trac15069-recursion_safe_callback.patch.gz With the patch that I have attached, the "recursion depth exceeded" problem seems to vanish. Let's see if the full test suite passes. |
comment:6
The tests pass for me. Needs review, then! |
comment:7
I don't think Python makes any guarantees that this is safe. The issue is precisely where the object is deallocated. As you noted, a local variable doesn't cut it as it gets destroyed while we are still in the "remove' function frame. A return value apparently works, but that is just an implementation detail of CPython. A different Python version might very well destroy returned-but-discarded values while still in the function frame. Its still better than before, so if you want to run with this workaround then that is fine with me. |
comment:8
Replying to @vbraun:
In the worst case we will get an explicit recursion error, some If yes, then I agree it's not yet perfect but safe enough to go I don't feel quite qualified for the fine technical details. Volker, Cheers, |
Reviewer: Volker Braun |
comment:9
At least we'll have a doctest, so if it breaks in the future we'll be notified ;-) |
Merged: sage-5.12.beta4 |
The following happens both with Sage's
MonoDict
and with Python'sweakref.WeakKeyDictionary
:Replace
M = MonoDict(11)
byM = weakref.WeakKeyDictionary()
, and you get essentially the same error:However, a
weakref.WeakValueDictionary
seems safe:even though the recursive deletion of dictionary items seems similar.
Aim of this ticket: Make it so that the erasers of
MonoDict
andTripleDict
are not recursively called and thus the dreaded 'maximum recursion depth exceeded ... ignored' finally vanishes.CC: @nthiery @nbruin @vbraun
Component: performance
Author: Simon King
Reviewer: Volker Braun
Merged: sage-5.12.beta4
Issue created by migration from https://trac.sagemath.org/ticket/15069
The text was updated successfully, but these errors were encountered: