#14159: Don't install callbacks on values of TripleDict, MonoDict
------------------------------+---------------------------------------------
       Reporter:  nbruin      |         Owner:  tbd                             
   
           Type:  defect      |        Status:  needs_work                      
   
       Priority:  major       |     Milestone:  sage-5.8                        
   
      Component:  memleak     |    Resolution:                                  
   
       Keywords:              |   Work issues:  Make part the coverage script 
happy
Report Upstream:  N/A         |     Reviewers:  Nils Bruin                      
   
        Authors:  Simon King  |     Merged in:                                  
   
   Dependencies:  #13387      |      Stopgaps:                                  
   
------------------------------+---------------------------------------------

Comment (by nbruin):

 Replying to [comment:22 SimonKing]:

 (just saw your new post. Definitely an option. If you see merit I'm fine
 with that. Below response I wrote to your earlier message)

 > I thought you diagnosed that this was the cause of one problem we saw?
 No, what I'm pretty sure we saw at some point was GC ''happening'' during
 dictionary value setting. While looking at the code I noticed this
 callback without proof that it's safe.

 > 1. Some parent X, Y give rise to a homset H, in a category C.
 > 2. H and X get deleted, but the callbacks are not performed yet. A new
 parent X2 is created, and by mere coincidence we have id(X)==id(X2).
 > 3. The homset H2 with respect to X2, Y and C is created. It thus
 overrides H in the cache.
 > 4. Finally, the callback of H is performed, erasing H2 from the cache.
 Boom

 Yes, that's exactly the scenario I envisaged. I don't have a proof that
 this is theoretically possible, though.

 The weakref to X is referenced by this dictionary that is still in use, so
 it's not garbage. I think that means the callback to X is guaranteed to
 happen before deallocation of X (and hence before the creation of X2).
 Furthermore X can only be found to be garbage if H is found to be garbage
 (because of the strong `domain` reference), so the callback on H has to
 happen in the same GC as the deallocation of X. So as long as we're not
 creating parents during callbacks, I think that also means X2 cannot be
 created in the same memory location as X while the callback on H hasn't
 happened yet.

 So we have a choice:
  - make a very involved argument, carefully reasoning about the specifics
 of python's GC system (for which we don't actually have a formal axiom
 system)
  - be on the safe side and just put in a cheap test.

 > Do you prefer that I erase this statement?

 perhaps "race condition we couldn't quite rule out"

 > Thinking of it: Suppose we are now considering the callback of X, which,
 in the above scenario, has not been called prior to the creation of X2.
 Would it not delete the new item, too? So, shouldn't we add a test in
 `TripleDictEraser.__call__(self, r)`, so that an item is deleted only if
 one of the references from the keys of this item is identical with r?

 No, in order to set the value, the caller must be holding strong
 references to the keys. As far as I know, weakref callback and
 deallocation only get separated inside GC. So as long as we're not calling
 set in callbacks, I think we're prevented from it (note that for H we
 needed, in addition, that H holds a reference to X AND that key triples do
 not get reassigned.)

 > I wouldn't like to put this into `TripleDict`. After all, it is
 impossible to prevent all thinkable typing mistakes.

 Well, this is one where you have to type the same data ''twice''. But I
 agree: We have only one use case. Should we get more I think it's worth
 reconsidering.

 > Additional idea: We could create TripleDict with an optional parameter
 weak_values. If this parameter is True, then the set/get methods would
 automatically use a weak reference on the value, with the correct key for
 the callback. Hence, we do not need to exploit implementation details when
 we apply a triple dict with weak values in sage.categories.homset

 Well, conceptually that's a different concept. Whether we want to
 implement that in the same structure (advantage: code reuse, disadvantage:
 increased complexity, possibly efficiency loss) is an engineering call.
 Again, for one use case I think it's not worth it. Should we find the need
 more often for such "fully weak associations" (we found the coercion
 system has tables that are a bit like this) we can reconsider.

 At the moment I'm getting a feeling we're entering the realm of
 overengineering.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/14159#comment:26>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to