-
-
Notifications
You must be signed in to change notification settings - Fork 491
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
Pickling with __reduce__() loops creates invalid pickles #15156
Comments
comment:1
I've posted on https://groups.google.com/d/msg/sage-devel/8EX3H7UKHcU/Z6MLdQCBCVUJ to make more people aware of this issue. |
comment:2
I think the circularity in this example arises from:
Note that by selecting The problem here is in
As you see, the cache is fed into the construction tuple, but the cache can (and does, in this case) easily lead to circularities. If the cache is to be pickled at all, it should be reinstated with a |
comment:3
Unfortunately, this is not the only source of circularity. There is also
which indiscriminately puts a whole dictionary in the construction parameters, which in this case contains the cached form of Basically, a dict can be modified (and really IS modified for caching purposes!), so it should never be included in construction parameters. If specific parameters are needed upon construction, those need to be extracted separately. |
Attachment: trac15156_preliminary.patch.gz preliminary step towards more setstate |
comment:4
With these changes in place, it seems that the example does pickle and unpickle OK. The problem here is really that pickle doesn't raise an error with these circularities. Given the definition of the protocol, it really seems this shouldn't work. Circular stuff needs to be put in place by |
comment:5
We should probably check:
This list is not complete. It was obtained by |
comment:8
I pushed one commit which contains an example on how I think the problem can be fixed. Is this how this problem could be addressed? What do you think? |
Branch: u/saraedum/ticket/15156 |
comment:10
I found this useful to find out which object causes the cyclic reference. It traverses the graph which
New commits:
|
Commit: |
Branch pushed to git repo; I updated commit sha1. New commits:
|
Dependencies: #15692 |
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:14
cPickle gets things wrong if any circularity is created in the first parameter returned by
With cPickle(pickle raises an assertion):
This is in particular a problem with Homsets. The
Often the domain or codomain reference back to the Homset somehow. I have no idea how to fix this. The domain is really needed here because it determines the class of the result and it is used for a lookup in a cache. Any ideas? |
comment:15
Replying to @saraedum:
I think that is more appropriately phrased as "the pickle protocol is not defined when construction parameters have circularities". You'd basically be asking for a
Note that the circular reference wasn't put there in the corresponding
Domain and codomain cannot possibly refer to the homset in their
Yes, domain and codomain are really part of a homset, so it's not unreasonable to make them part of the We've see problems before where |
comment:16
Replying to @nbruin:
Right. But this is hard to do automatically.
I'm not sure what you mean by "instantiation phase".
Sure. But when pickling you do not only want to restore the initial state of an object but also to some extent the current state. Here is an idea how to solve the problem with restoring the state. Say we have
and make
With
There is of course lots of space for improvement, but what do you think about this idea? |
comment:17
Replying to @saraedum:
Unpickling an object happens in two phases: first, the object is instantiated using the first set of parameters given by The second phase is done by Pure python classes pickle great. They can have all kinds of circularities, but they're all stored in
I think it's a bad idea because it doesn't solve the problem where it needs to be solved. Homsets fundamentally need domain and codomain for their construction. It's part of their hash. If a parent wants to include a homset in its construction parameter rather than in the If the domain and codomain want to store a homset involving them somewhere, then their unpickling should do so via Circularities in |
comment:18
Replying to @nbruin:
I don't think that's really what happens. Maybe I misunderstand what you are saying but I don't think that all objects in the pickle are instantiated and then all objects'
This is not what happens. Here is a real-world example:
That's what happens above and does not work. I'm also confused because I always assumed that it would be enough to break the circularity on the first parameter in a single place. Somehow this does not seem to work. |
comment:19
Replying to @saraedum:
Not all objects. Just all objects that are involved making the relevant
That is indeed puzzling. Would python
Also for your earlier example, it looks like the pickle produced by dumps should be just fine:
Well -- it does not work in the sense that I did a quick search on whether this is a known problem, but I didn't find compelling evidence. Closest was this discussion |
comment:20
Replying to @nbruin:
Thanks for pointing this out. I just assumed that the AssertionError was pointing at an invalid pickle but you are right, my example actually works with cPickle. I'll see if this explains the errors I've seen while working on this ticket. |
Changed author from SimonKing, jkeitel, novoselt, nbruin to SimonKing, Jan Keitel, Andrey Novoseltsev, Nils Bruin |
Changed author from SimonKing, Jan Keitel, Andrey Novoseltsev, Nils Bruin to Simon King, Jan Keitel, Andrey Novoseltsev, Nils Bruin |
cPickle creates invalid pickles when
__reduce__()
loops are present, but no error message is raised. The only symptom are corrupt pickles. For example (thanks to Jan for isolating this):Although there is no error, the object is not correctly reconstructed:
Using pickle instead of cPickle gives an assertion:
This is correct, as the objects are traversed we eventually hit the
FanMorphism
object again as it is saved byCachedMethodCallerNoArgs.__reduce__
in a circular manner.This then leads to a corrupt pickle as the pickle bins get out of sync with the objects:
This is a known upstream bug, see http://bugs.python.org/issue1062277
Depends on #15692
Component: misc
Author: Simon King, Jan Keitel, Andrey Novoseltsev, Nils Bruin
Branch/Commit: u/saraedum/ticket/15156 @
82ba456
Issue created by migration from https://trac.sagemath.org/ticket/15156
The text was updated successfully, but these errors were encountered: