Skip to content
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

Data race on tp_flags with subinterpreters and static types #129817

Open
colesbury opened this issue Feb 7, 2025 · 0 comments
Open

Data race on tp_flags with subinterpreters and static types #129817

colesbury opened this issue Feb 7, 2025 · 0 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-free-threading topic-subinterpreters type-bug An unexpected behavior, bug, or error

Comments

@colesbury
Copy link
Contributor

colesbury commented Feb 7, 2025

Bug report

I saw this in the free threading build when running test_concurrent_futures.test_interpreter_pool. I suspect it affects the default build (with per-interpreter GIL) as well, but I haven't verified that.

The fix looks straightforward to me: only set Py_TPFLAGS_READY if initial is true. Otherwise, the type will already have Py_TPFLAGS_READY set.

WARNING: ThreadSanitizer: data race (pid=1450991)
  Write of size 8 at 0x555555d46628 by thread T2:
    #0 type_ready /raid/sgross/cpython/Objects/typeobject.c:8662:20 (python+0x302724) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #1 init_static_type /raid/sgross/cpython/Objects/typeobject.c:8732:11 (python+0x302d01) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #2 _PyStaticType_InitBuiltin /raid/sgross/cpython/Objects/typeobject.c:8750:12 (python+0x303013) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #3 _PyTypes_InitTypes /raid/sgross/cpython/Objects/object.c:2430:13 (python+0x2a6afb) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #4 pycore_init_types /raid/sgross/cpython/Python/pylifecycle.c:710:14 (python+0x4b85d9) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #5 pycore_interp_init /raid/sgross/cpython/Python/pylifecycle.c:861:14 (python+0x4b8375) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #6 new_interpreter /raid/sgross/cpython/Python/pylifecycle.c:2317:14 (python+0x4b5063) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #7 Py_NewInterpreterFromConfig /raid/sgross/cpython/Python/pylifecycle.c:2350:12 (python+0x4b4baa) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #8 _PyXI_NewInterpreter /raid/sgross/cpython/Python/crossinterp.c:1936:23 (python+0x44d91e) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #9 interp_create /raid/sgross/cpython/./Modules/_interpretersmodule.c:631:13 (_interpreters.cpython-314t-x86_64-linux-gnu.so+0x3b8e) (BuildId: cbf13907b53ea6706466f16badeadb9cd6f8a096)
...

  Previous read of size 8 at 0x555555d46628 by main thread:
    #0 lookup_tp_dict /raid/sgross/cpython/Objects/typeobject.c:395:15 (python+0x2f7366) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #1 find_name_in_mro /raid/sgross/cpython/Objects/typeobject.c:5448:26 (python+0x2f7366)
    #2 _PyType_LookupRefAndVersion /raid/sgross/cpython/Objects/typeobject.c:5611:11 (python+0x2f6e5f) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #3 _PyType_LookupRef /raid/sgross/cpython/Objects/typeobject.c:5659:12 (python+0x2f3480) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #4 _PyObject_GenericGetAttrWithDict /raid/sgross/cpython/Objects/object.c:1687:13 (python+0x2a2bed) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #5 _Py_module_getattro_impl /raid/sgross/cpython/Objects/moduleobject.c:937:12 (python+0x29931c) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #6 _Py_module_getattro /raid/sgross/cpython/Objects/moduleobject.c:1084:12 (python+0x299800) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
    #7 PyObject_GetAttr /raid/sgross/cpython/Objects/object.c:1289:18 (python+0x2a1407) (BuildId: 8b1677c857cece976d8e5c76092eb8d5e05609fe)
...

Write of tp_flags:

cpython/Objects/typeobject.c

Lines 8661 to 8663 in fbaa6c8

/* All done -- set the ready flag */
type->tp_flags |= Py_TPFLAGS_READY;
stop_readying(type);

Read of tp_flags:

static inline PyObject *
lookup_tp_dict(PyTypeObject *self)
{
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
PyInterpreterState *interp = _PyInterpreterState_GET();
managed_static_type_state *state = _PyStaticType_GetState(interp, self);
assert(state != NULL);
return state->tp_dict;
}
return self->tp_dict;
}

Linked PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-free-threading topic-subinterpreters type-bug An unexpected behavior, bug, or error
Projects
Status: Todo
Development

No branches or pull requests

2 participants