Skip to content

gh-137238: Fix data race in _Py_slot_tp_getattr_hook #137240

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

colesbury
Copy link
Contributor

@colesbury colesbury commented Jul 30, 2025

Replacing the slot isn't thread-safe if the GIL is disabled. Don't require that the slot has been replaced when specializing.

Replacing the slot isn't thread-safe if the GIL is disabled. Don't
require that the slot has been replaced when specializing.
@@ -935,8 +935,7 @@ analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, un
PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
has_getattr = getattr != NULL;
if (has_custom_getattribute) {
if (getattro_slot == _Py_slot_tp_getattro &&
!has_getattr &&
if (!has_getattr &&
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Fidget-Spinner, I removed the getattro_slot == _Py_slot_tp_getattro check here because:

  1. It would prevent specialization of __getattribute__ Python calls in the free threaded build with this change
  2. I don't think it's necessary. The combined has_custom_getattribute and !has_getattr checks are sufficient.

Does this make sense to you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense for the FT build. Just reasoning out loud here: From what I see above, we replace the NULL slot with the special "__getattribute__ but no __getattr__" slot at some lookup time. But it's functionally the same as just saying get_attr == NULL. So the check for the slot is redundant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I should add that we already check getattro_slot == _Py_slot_tp_getattr_hook || getattro_slot == _Py_slot_tp_getattro above.

Another way of saying this:

  1. There's a C pseudo-specialization process of rewriting _Py_slot_tp_getattr_hook to _Py_slot_tp_getattro
  2. The Python specialization of rewriting LOAD_ATTR to LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN shouldn't require _Py_slot_tp_getattr_hook to have already replaced by _Py_slot_tp_getattro. It just needs to ensure the conditions are correct (i.e, __getattribute__ is present, __getattr__ is not and the getattro_slot isn't overridden with something else)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants