neunhoef/io — pull request #11 by ChrisJefferson (2014-04-21 15:07:01+00:00)
Title: Cache obs when IO_Pickling

This bug took me a while to track down. I'm fairly convinced it is a bug, just that my PartialPerm and Transformation picklers are the first to uncover it.

The problem was hard to track down, the fix is easy :)

The problem is that the IO's PickleCache uses 'IO_MasterPointerNumber' (which gives the GAP memory bag number) to decide if two objects are the same. The problem is that if an IO_Pickle function creates a temporary variable which is recursively IO_Pickled (which several do), then this objects can be garbage collected, and another objects created with the same master pointer. IO's Pickle Cache then thinks these are the same object.

The easy fix is just to cache the object in IO_AddToPickled, which ensures no temporary is thrown away until we have finished pickling. While this might cause memory usage increase during IO_Pickle, during IO_Unpickle a reference to every object is stored anyway, so this can't make code break that worked before. At the same time, for clarity, I standardised on always calling IO_ClearPickleCache to clear out the cache, rather than trying to cleverly only clean out some parts of the cache.

The reason (I think) no-one has hit this before (although I haven't carefully checked every function), is you have to

(a) create temporary variables
(b) create enough temporary variables that a garbage collection occurs
(c) those temporary variables must be 'complex enough' that IO_AddToPickled is called for them.

The PartialPerm and Transformation picklers both generate temporary lists, which hit all these bullet points.