-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
bpo-37270: Manage memory lifetime for all type-related objects. #14066
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
base: main
Are you sure you want to change the base?
Conversation
I can reproduce the error locally and have begun working on a fix. I realized we also need to handle the |
Could these two be separated in two different PRs? In interested in particular to review the part dealing with |
They could be broken up, but there is little value in doing just one of the three (PyMethodDef, PyGetSetDef, and now also PyMemberDef). The goal is to not be forced to leak memory when making types. I could do a better job of breaking this into 3 commits though. |
I agree with that, I never suggested to do just one of the three. I suggested breaking it up because I think that 3 simpler PRs have a higher chance of getting reviewed than 1 big one. (at least, this is true if I would be the reviewer)
If you make 3 commits, you might as well make 3 PRs. |
The only thing that you need is to guarantee that Py_tp_members will be alive throughout the life-cycle of the type. This is easily achieved by storing the data within the type itself. I just responded in the capi-sig list into how you can do that. It has been done with Py_tp_members before, it just needs to be updated to work with Py_tp_methods: https://mail.python.org/archives/list/capi-sig@python.org/thread/RNNJRKKWDHM5FUERFLSWL6JSI2UVURIS/ Btw your change breaks the continuous builds :) |
4d1fa96
to
e481956
Compare
Remove internal usages of PyMethodDef and PyGetSetDef. For PyMethodDef, change PyCFunctionObject to replace the PyMethodDef* member with a PyCFunctionBase member. The PyCFunctionBase is a new struct to hold the managed values of a PyMethodDef. This type is shared between PyCFunction and the various callable descriptor objects. A PyCFunctionBase is like a PyMethodDef but replaces the char* members with PyObject* members. For PyGetSetDef, inline the members on the resulting PyGetSetDescrObject, replacing all char* members with PyObject* members. The memory for the closure is *not* managed, adding support for that would likely require an API change and can be done in a future change. For the tp_name field, instead of setting it directly to the value of PyType_Spec.name, set it to the result of PyUnicode_AsUTF8(ht_name), where ht_name is the PyUnicode object created from the original spec name. This is the same trick used to properly manage this pointer for heap types when the __name__ is reassigned.
e481956
to
fb1bc5e
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.
You are trying to do too many things at once. This change is not reviewable as is, you are mixing in code formatting, new C-APIs, changes to current C-APIs, etc. You need to break the code up into smaller chunks. Also, use PEP8 to guide your code style.
Btw, this breaks backwards compatibility both in the ABI and in functionality. Your code change must not break either of these, it should only be additive. It is indeed possible to fix your problem while maintaining these invariants.
Which ABI does it break? |
This will likely conflict with my #13781, so I would prefer if that PR could be merged first. |
The only interface I believe this affects is iterating over the I see that it is large change, but I don't believe this is part of the stable ABI. Also, we can't just copy the arrays backing the |
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.
Now that #13781 is merged, this needs to be rebased to master.
I remind you that I agree with the general approach here, but that the PR would better be split up in smaller pieces.
@llllllllll, please resolve the merge conflicts. Thanks! |
Remove internal usages of PyMethodDef and PyGetSetDef.
For PyMethodDef, change PyCFunctionObject to replace the PyMethodDef* member
with a PyCFunctionBase member. The PyCFunctionBase is a new struct to hold the
managed values of a PyMethodDef. This type is shared between PyCFunction and the
various callable descriptor objects. A PyCFunctionBase is like a PyMethodDef but
replaces the char* members with PyObject* members.
For PyGetSetDef, inline the members on the resulting PyGetSetDescrObject,
replacing all char* members with PyObject* members. The memory for the closure
is not managed, adding support for that would likely require an API change and
can be done in a future change.
For the tp_name field, instead of setting it directly to the value of
PyType_Spec.name, set it to the result of PyUnicode_AsUTF8(ht_name), where
ht_name is the PyUnicode object created from the original spec name. This is the
same trick used to properly manage this pointer for heap types when the name
is reassigned.
https://bugs.python.org/issue37270