[3.13] gh-127065: Make methodcaller thread-safe in free threading build (GH-127109) (GH-127150)

The `methodcaller` C vectorcall implementation uses an arguments array
that is shared across calls. The first argument is modified on every
invocation. This isn't thread-safe in the free threading build. I think
it's also not safe in general, but for now just disable it in the free
threading build.
(cherry picked from commit f83ca6962a)

Co-authored-by: Sam Gross <colesbury@gmail.com>
This commit is contained in:
Miss Islington (bot) 2024-11-22 15:51:40 +01:00 committed by GitHub
parent 1b58c0f308
commit 5468d219df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 0 deletions

View file

@ -1572,6 +1572,7 @@ typedef struct {
vectorcallfunc vectorcall;
} methodcallerobject;
#ifndef Py_GIL_DISABLED
static int _methodcaller_initialize_vectorcall(methodcallerobject* mc)
{
PyObject* args = mc->xargs;
@ -1634,6 +1635,7 @@ methodcaller_vectorcall(
(PyTuple_GET_SIZE(mc->xargs)) | PY_VECTORCALL_ARGUMENTS_OFFSET,
mc->vectorcall_kwnames);
}
#endif
/* AC 3.5: variable number of arguments, not currently support by AC */
@ -1673,7 +1675,14 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
mc->vectorcall_args = 0;
#ifdef Py_GIL_DISABLED
// gh-127065: The current implementation of methodcaller_vectorcall
// is not thread-safe because it modifies the `vectorcall_args` array,
// which is shared across calls.
mc->vectorcall = NULL;
#else
mc->vectorcall = (vectorcallfunc)methodcaller_vectorcall;
#endif
PyObject_GC_Track(mc);
return (PyObject *)mc;