diff options
author | Sam Gross <colesbury@gmail.com> | 2024-11-22 14:21:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-22 14:21:59 (GMT) |
commit | f83ca6962af973fff6a3124f4bd3d45fea4dd5b8 (patch) | |
tree | a0d5d30ccf66eab3390e3424c7839bfc6be8c726 /Modules/_operator.c | |
parent | 3c770e3f0978d825c5ebea98fcd654660e7e135f (diff) | |
download | cpython-f83ca6962af973fff6a3124f4bd3d45fea4dd5b8.zip cpython-f83ca6962af973fff6a3124f4bd3d45fea4dd5b8.tar.gz cpython-f83ca6962af973fff6a3124f4bd3d45fea4dd5b8.tar.bz2 |
gh-127065: Make `methodcaller` thread-safe in free threading build (#127109)
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.
Diffstat (limited to 'Modules/_operator.c')
-rw-r--r-- | Modules/_operator.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/Modules/_operator.c b/Modules/_operator.c index 7e0d1f3..6c19451 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -1602,6 +1602,7 @@ typedef struct { vectorcallfunc vectorcall; } methodcallerobject; +#ifndef Py_GIL_DISABLED static int _methodcaller_initialize_vectorcall(methodcallerobject* mc) { PyObject* args = mc->xargs; @@ -1664,6 +1665,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 */ @@ -1703,7 +1705,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; |