-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
Updated memory management #543
Conversation
@mhsmith, care to have first look? Please note the TODOs still listed above. |
89a4d62
to
931c352
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This turned out to be a lot less invasive than I thought it would be.
I've done a check of the toga-chart issue that triggered this change; and it seems to resolve that problem.
I also did a quick check with Toga's testbed suite on macOS; that code has a bunch of manual retain
s and autorelease
/release
s. I thought they should all be balanced though - worst case, objects would be over-retained - so I was a little surprised that it the testbed segfaults almost immediately (and the stack trace doesn't give any obvious pointers what is causing the issue).
If I remove all the retains and releases, the testbed segfaults; but on inspection, some of the uses are for objects that are created in Python, then handed to ObjC to manage (e.g., Toolbar items created here), or the copyWithZone
handler here). But I guess those uses of memory handling make sense - and they're a lot closer aligned to the "spirit" of ObjC memory handling, Plus, in at least the ToolbarItem case, it could be avoided by keeping the toolbar instance in the cache of items.
Related - if we land this, I suspect a version bump to 0.5 might be called for. This is just backwards incompatible enough that I think it's worth flagging the significance of the change. |
Thanks for the thorough checks! I've updated the PR description to give a better summary of the change and also discuss why this should be non-breaking for most users. I'll have a closer look at the segfaults that you encountered, later. They might be caused by the usage of Maybe there are also ways to prevent users from shooting themselves in the foot, e.g., raise an exception on manual release calls if there is only a single reference left. |
Thanks, this looks great. I'm busy today, but I'll take a look at this as soon as I can. |
I've had a closer look now at the segfaults and could identify two cases where they happen:
beeware/toga#2978 contains all the changes that I found to (1) prevent segfaults and (2) remove now unneeded manual memory management. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Co-authored-by: Malcolm Smith <[email protected]>
6648cd0
to
f0edb5b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this PR as it stands now; in addition to solving the originally reported problem (beeware/toga-chart#191), it solves the bigger problem of memory management (#256) problem; it addresses the remaining iOS leakage issues (see beeware/toga#2853); and apparently also fixes a method caching issue that has been unreported to date.
I've left one comment about the argument used when constructing arguments, but that's a minor cleanup suggestion, and one that I'll gladly back down from if you disagrees.
Before we merge, I'd also like @mhsmith's final review in case he can think of any edge cases or other issues I might have missed.
if self.superclass.methods_ptr is None: | ||
with self.superclass.cache_lock: | ||
self.superclass._load_methods() | ||
# Traverse superclasses and load methods. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the method lookup isn't strictly related to the memory retention issue, but I'm OK with the level of complexity it adds to this PR in the interest of addressing some issues that we know exist when this PR is used in Toga.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this solution as well. Just a few more comments:
…in ARC docs Co-authored-by: Malcolm Smith <[email protected]>
…se separators Co-authored-by: Malcolm Smith <[email protected]>
Co-authored-by: Malcolm Smith <[email protected]>
Thanks again for doing this! |
Never would I have dreamed that one graph resizing incorrectly would lead to all this work! Hats off for sure! |
Echoing what @mhsmith said - a huge thanks for this. This removes a huge wart on Rubicon's design; and as the Toga update PR highlights, resolves a bunch of weird edge cases and memory issues. Following up on this comment - should I cut a 0.5.0 release now, or do you want me to hold off until you've had a chance to take a swing at that update as well? There's no particular pressure to get a release out the door, but given this is a big change, it feels like we should make it official sooner rather than later so that the impact isn't forgotten. |
I am happy with you to go ahead with 0.5.0 release. The methods-loading update should be entirely under the hood, without any breaking changes, so will be a easy one to follow in 0.5.1 but also with viewer benefits to users. There are also still a few issues my methods loading update #547 and I might not get to them until end of next week. |
This PR changes the memory management model of Rubicon. Previously, we would release objects on Python
__del__
calls only if we created them ourselves and own them from alloc and similar calls.In this PR, we always ensure that we own objects when we create a Python wrapper, by explicitly calling
retain
if we did not get them fromalloc
etc and always callingautorelease
when the Python wrapper is garbage collected. This has a few advantages:This change should be backward compatible for most users because existing manual
retain
andrelease
calls don't cause any issues if balanced and would have already caused segfaults if there are more releases than retains.TODO:
PR Checklist: