#14159: Don't install callbacks on values of TripleDict, MonoDict
---------------------------------+------------------------------------------
       Reporter:  nbruin         |         Owner:  tbd     
           Type:  PLEASE CHANGE  |        Status:  new     
       Priority:  major          |     Milestone:  sage-5.8
      Component:  PLEASE CHANGE  |    Resolution:          
       Keywords:                 |   Work issues:          
Report Upstream:  N/A            |     Reviewers:          
        Authors:                 |     Merged in:          
   Dependencies:                 |      Stopgaps:          
---------------------------------+------------------------------------------

Comment (by nbruin):

 Replying to [comment:8 SimonKing]:
 > Hm. This particular `TripleDict` is only used by hom, and hom doe not
 override an existing entry. So, this particular case should be safe.
 However, it still seems reasonable to me to let the callback check whether
 the to-be-deleted value did not change.

 I was fully expecting that to be true, but I could not come up with an
 explanation for the bug Jeroen reported at #12313, where the line in
 {{{
  _cache[key] = KeyedRef(H, _cache.eraser, (id(X),id(Y),id(category)))
 }}}
 leads to a key error in `TripleDict.set` in the line:
 {{{
 r1,r2,r3 = <tuple>(self._refcache[h1,h2,h3])
 }}}
 The only thing I could think of for that line to fail is:
  - This `KeyedRef` object `W` is constructed
  - `_cache.set(k1,k2,k3,W)` is called with
 `k1=id(X),k2=id(Y),k3=id(category)`. Note that the caller is holding
 strong references to `(X,Y,category)`.
  - In order to end up in the line `r1,r2,r3 =
 <tuple>(self._refcache[h1,h2,h3])`, the key triple `(k1,k2,k3)` must be
 present in this `TripleDict` and hence in `self._refcache`
  - Yet, we get a `KeyError`. Calling `self._refcache[h1,h2,h3]` requires
 the construction of a new tuple `(h1,h2,h3)`, which could trigger a `GC`
 and hence a callback that would remove entries. So the only explanation I
 see is that we're getting a callback with key `(k1,k2,k3)` due to a GC
 triggered by this tuple allocation.
  - However, this callback cannot result from any of `X,Y,category` getting
 collected, because someone is holding strong references to them. Hence
 such a callback must be coming from somewhere else.
  - The code pointed to (ironically the same code that triggers this
 `TripleDict` operation) is an example of code that installs such
 callbacks. So a possible scenario is that a statement
 {{{_cache.set(k1,k2,k3,Wold)}}}
 was executed before, that Wold is still hanging around in memory and that
 it finally gets removed due to this poorly timed garbage collection and
 consequently that the keytriple `(k1,k2,k3)` receives a callback, even
 though they are pointing to (or are about to be pointing to -- we don't
 know what happened in between) another, unrelated value.

 In this scenario, values in this `Hom` dictionary do get changed.

 We need to ensure that `TripleDict` cannot trigger `GC` at that point
 anyway (and that is what #13387 does as a side-effect), because all kinds
 of other bad things could happen as well. However, given that it needs
 such a complicated explanation, I would hope we can verify my assumptions,
 because otherwise my fix might not be sufficient.

 Hence the formulation of the ticket: If you can prove that installing this
 callback is safe, I have no problem with it.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/14159#comment:9>
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