Description
What is the problem or limitation you are having?
In the process of building the Toga GUI testbed, we discovered #249. A fix for this problem was included in #246; however, that fix was really a safety catch for a specific set of circumstances. The bigger question: how did that set of circumstances happen in the first place?
At present, it is possible for an object to be disposed of by Objective C, but due to delays in propagating garbage collection, the ObjCInstance
wrapping that object may not be immediately disposed of. This means the weak reference dictionary can contain stale objects.
#246 protected against this by protecting against the specific case where a memory address was reused - but if a Python object points at memory that has been disposed of and not reused, you'll generate a segfault. This is obviously undesirable.
Describe the solution you'd like
Functionally - it should be impossible to generate a segfault from Python code.
An idea posited by @mhsmith in the discussion about #249 was that we could maintain stronger reference to the ObjC object on the Python side. This would mean we add add a retain
calls whenever a Python-side wrapper is created; release
-ing only when Python has finished with the object. The idea here would be that it's better to have larger memory footprint (or even a small leak), than to have a segfault because a Python object has a stale memory reference.
Describe alternatives you've considered
Do nothing. The status quo is stable(ish?), and while it, may be theoretically possible to get a stale ObjCInstance object, in practice we're not seeing that problem (after #246 landed, anyway).
Additional context
Other than the general hesitation of fiddling with a complex area of code that appears to work at present - the complication to watch out for here is cyclic references between Python objects and Objective C objects that prevents Objective C from ever releasing memory. It's easy to avoid segfaults by never releasing... but eventually the memory will run out.