-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
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
An object referenced only through it's own __dict__
can get collected too early.
#130327
Comments
I suspect it's probably something about |
I haven't fully figured it out, but it seems the problem is (somewhat) here: Line 7174 in 5a13faa
The dictionary is being stored in the object's managed pointer, but the original object still assumes it has ownership, so it clears it upon being deallocated. We need to detach ownership upon doing that, or copy the inline values of |
I think the issue is in Lines 7146 to 7164 in 6c450f4
If there's a managed dictionary, we should visit the dictionary, not the inline values, even if the values are "valid". |
Thanks for the insight, Sam. I haven't dived into these parts of the codebase before, so bear with me here. I'm not sure it's possible for an object to have valid inline values while also having a non-null managed dictionary. The relevant code that sets the managed dictionary pointer also immediately invalidates the inline values: Lines 7174 to 7181 in 5a13faa
Hmm. If not |
Yes, this is allowed and fairly common. It allows fast access to the attributes via class MyObj: pass
a = MyObj()
a.attr = "value"
d = a.__dict__ # a now has a managed dictionary and still has valid inline values
tmp = a.attr # this will be specialized to `LOAD_ATTR_INSTANCE_VALUE` if executed enough times
That's the code path for changing the managed dictionary. For example, So when we have: a = A()
b = A()
b.__dict__ = A.__dict__
Yes, The bugs are in Concretely, what's happening is:
So now What should happen?There's ambiguity here because for objects like I think the logic should be:
Basically, we should treat it as if the dictionary owns the values, not the object. |
Bug report
Bug description:
After reusing one object's
__dict__
for another object, and adding a reference to the original object in a dictionary on the target object, the original object might get collected too early (and cause a whole other dictionary to get cleared). I hope the code below describes it better than my words.I've bisected this problem to c32dc47.
This is the smallest reproduction I've found so far:
Results on 3.13:
Results on 3.12, and what I expected to see:
I've noticed this change in behaviour while working with Locust.io, the original issue for reference: locustio/locust#3050
CPython versions tested on:
3.13, CPython main branch
Operating systems tested on:
Linux
The text was updated successfully, but these errors were encountered: