-
-
Notifications
You must be signed in to change notification settings - Fork 481
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
Better deletion of items of TripleDict #13904
Comments
Attachment: trac_13904_fix_del.patch.gz Attempt to fix |
comment:1
There's the more severe problem that during GC cleanup, a weakref callback could lead to the deletion of a non-weakreffable key, which could retrigger the dealloc of the object that has just generated the weakref. That would lead to a double dealloc. The following might be a solution:
Deathrow will be cleaned up eventually, as part of the regular cleanup code for deallocation of TripleDict. The problem is that weakref callback operates in a strange environment: There is a dealloc call higher up the stack somewhere. Normally python code doesn't run under those circumstances. It shouldn't make much difference, but you should absolutely not delete that object again. Hence, I think the default should be: Don't delete objects in callback. You can modify this rule, but only on a case-by-case basis, by carefully reasoning that the deletions that you do allow won't lead to nasty unpredictable deletion cascades. |
comment:2
I don't think we need this ticket for the |
comment:3
Nils, indeed it might be an idea to use the ideas from #13387. However, the ticket here is not about optimization. Anyway. I am starting with Sage's debug version as in #13864. With the first patch applied, one gets a crash in modules/module.pyx With both patches applied, one gets
So, that looks like a progress. However, at least with a slightly different version of the first patch, make ptest still results in
when both patches are applied. Note, however, that I can not reproduce these crashes when I run them independently. Hence, one needs to dig deeper. See comment:1. |
comment:4
Replying to @nbruin:
Ah, you say that the problem actually isn't so much the |
comment:5
Oops, I just notice that the patch attempts to fix |
comment:6
Replying to @simon-king-jena:
The One way to solve this would be to forbid non-weakreffable container types to be used as keys. The problem is that I can't think of a reliable test for that. Since the consequences of violating might lead to incredibly insidious memory corruptions, I think we should guard against it. A consequence is that any non-weakreffable (non-whitelisted such as None or int) key automatically has its life span bounded below by the lifetime of the |
comment:7
Replying to @nbruin:
Is what you describe as follows? Let's say we have a key Or did I misunderstand? Can you elaborate a bit more, please? |
comment:8
Replying to @simon-king-jena:
Yes, that's correct. It would have to be a strong reference from B to A, because deletion of weakrefs should not trigger deletion cascades. Of course, that means the reference count to A isn't 0, so normally A would not be eligible for deletion ... but if A and B are found to be cyclic garbage, deallocation could still occur. We'd be at the mercy of GC for how the chain gets broken up and deleted. In fact, moving B to
as a key, which doesn't immediately look completely unlikely. We don't generate keys like that, but someone else might ... |
comment:9
Replying to @nbruin:
PS: Why can this only happen with a non-weakreffable key? In particular, what are the keys in our crashing example? Namely, in its current use, I don't think that there are any non-weakreffable keys other than None and ints.
One could provide a new method Perhaps Problem could be a severe slow-down. |
comment:10
Replying to @simon-king-jena:
The cython-induced crash has only weakreffable keys. The hypothetical behaviour has not been observed.
But arbitrary code can be executed during weakref callbacks, including arbitrary Really, this is starting to look more like a design deficiency in CPython: it should really mark objects on which dealloc is running to prevent GC, decref, whatever, from reentering dealloc. Preventing this by code protocol just seems to unduly restrict allowed data structures.
You wouldn't be sure that deathrow entries are now safe to delete ... EXECUTIVE DECISION: we mandate that key components to |
comment:11
Replying to @nbruin:
... and is an upstream bug in Cython?
Not quite, because we Know exactly what is happening in our weakref callbacks (namely: In the
Agreed.
I guess this would be the easiest solution on the short run. Do you think of a whitelist, i.e., explicitly allowing |
comment:12
By the way, my first attachment is wrong anyway, because I mispelled |
For debugging only. Increase the likelyhood that a gc occurs during a weakref callback |
comment:13
Attachment: trac_13904_debug_only.patch.gz The "debug_only" patch is updated. With it, I tried the following:
That should be exactly the theoretical situation you were describing, isn't it? But there is no crash. When I interrupt it after a while, with Ctrl-C, I get
This I don't understand. Is |
comment:14
Replying to @simon-king-jena:
Well, certainly the weak keys can be cleared. But apparently they can not be cleared, if there is a non-weakreffable item in the key that holds a reference to a weakreffable item in the key. Hence, on the one hand, it seems that the situation you constructed is a non-issue, because the callback function for the weak reference will not be called. On the other hand, it is yet another reason to not allow non-weakreffable containers as key. |
Script that tries to cause a double dealloc but fails because python is mature |
comment:15
Attachment: test.sage.gz HOORAY! |
comment:16
Replying to @simon-king-jena:
No, nothing is broken. You haven't included the definition of Although you delete Things are collectible once you throw away |
comment:17
Replying to @nbruin:
OK. But I wouldn't like to resolve this ticket as "wontfix" or "duplicate". Still, we should use "del", not " |
Dependencies: #13896 |
comment:19
Replying to @simon-king-jena:
Yes, go ahead. Since there is no urgent issue anymore, use this ticket for whatever you want (and yes, that cython does solve the problem, if you compile the whole library with it. I'm now pretty confident I know exactly what went wrong, after seeing it happen on bit-level ...). The |
comment:22
Can we get the change from From what I've really quickly read, Nils pointed out another problem with weakrefs and callbacks, but let's go one step at a time and deal with that elsewhere (or move the trivial fix on a separate ticket). |
comment:23
Oh in fact, I've read a little less quickly and the problem Nils thought about does not occur? And in case one really wants to let garbage collection occurs during weakref callback or whenever, there are always ways to do that. |
Use del rather then calling |
comment:26
Attachment: trac13904_use_del.patch.gz I think using The new patch uses Apply trac13904_use_del.patch |
Author: Simon King |
This comment has been minimized.
This comment has been minimized.
Reviewer: Jean-Pierre Flori |
Merged: sage-5.8.beta0 |
Changed merged from sage-5.8.beta0 to none |
comment:31
Unmerging because of trouble with #12313. |
comment:32
Perhaps try #13387 instead? With the solution there, this ticket is superseded there. It improves the performance of these dictionaries in some other ways as well. |
Changed reviewer from Jean-Pierre Flori to Simon King, Jean-Pierre Flori |
Changed author from Simon King to none |
In #715,
TripleDict
has been modified, so that the key items are compared by identity rather than equality, and so that weak keys are used when possible.However, as it turns out, the deletion of the items tracked in a
TripleDict
was done improperly. The aim of this ticket is to fix that.Superseded by #13387.
Depends on #13896
Depends on #12313
CC: @nbruin @vbraun @jpflori
Component: memleak
Reviewer: Simon King, Jean-Pierre Flori
Issue created by migration from https://trac.sagemath.org/ticket/13904
The text was updated successfully, but these errors were encountered: