Skip to content

Data race in functools.partial in Python 3.14 #143880

@colesbury

Description

@colesbury

Bug report

Seen by @ngoldbaum in NumPy in numpy/numpy#30653 (comment)

WARNING: ThreadSanitizer: data race (pid=15392)
  Read of size 8 at 0x00010b6de6f8 by thread T325:
    #0 object_vacall call.c:820 (libpython3.14t.dylib:arm64+0x8e0f4)
    #1 PyObject_CallFunctionObjArgs call.c:927 (libpython3.14t.dylib:arm64+0x8e49c)
    #2 array_str <null> (_multiarray_umath.cpython-314t-darwin.so:arm64+0x254dd8)
    #3 PyObject_Str object.c:822 (libpython3.14t.dylib:arm64+0x13834c)
...

  Previous write of size 8 at 0x00010b6de6f8 by thread T327:
    #0 partial_vectorcall_fallback _functoolsmodule.c:378 (libpython3.14t.dylib:arm64+0x424f94)
    #1 partial_vectorcall _functoolsmodule.c:393 (libpython3.14t.dylib:arm64+0x4248dc)
    #2 object_vacall call.c:820 (libpython3.14t.dylib:arm64+0x8e110)
    #3 PyObject_CallFunctionObjArgs call.c:927 (libpython3.14t.dylib:arm64+0x8e49c)

The relevant code is:

Py_NO_INLINE static PyObject *
partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
PyObject *const *args, size_t nargsf,
PyObject *kwnames)
{
pto->vectorcall = NULL;
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
return _PyObject_MakeTpCall(tstate, (PyObject *)pto, args, nargs, kwnames);
}

The assignemnt pto->vectorcall = NULL leads to a data race in the free threading build.

This is fixed in main. We should fix it in 3.14 by guarding that assignment with an #ifndef Py_GIL_DISABLED

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions