diff options
author | Sam Gross <colesbury@gmail.com> | 2024-06-03 22:21:32 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-03 22:21:32 (GMT) |
commit | ae705319fcde864b504987dc8e579e3eef68e1e5 (patch) | |
tree | 022166446a352d99b784b44a86f163bec179e94d /Modules | |
parent | ca37034baa2909722df58c02dfd13e1d667252ce (diff) | |
download | cpython-ae705319fcde864b504987dc8e579e3eef68e1e5.zip cpython-ae705319fcde864b504987dc8e579e3eef68e1e5.tar.gz cpython-ae705319fcde864b504987dc8e579e3eef68e1e5.tar.bz2 |
[3.13] gh-117657: Fix race involving immortalizing objects (GH-119927) (#120005)
The free-threaded build currently immortalizes objects that use deferred
reference counting (see gh-117783). This typically happens once the
first non-main thread is created, but the behavior can be suppressed for
tests, in subinterpreters, or during a compile() call.
This fixes a race condition involving the tracking of whether the
behavior is suppressed.
(cherry picked from commit 47fb4327b5c405da6df066dcaa01b7c1aefab313)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testinternalcapi.c | 24 |
1 files changed, 9 insertions, 15 deletions
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 129c136..8c65b80 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1965,24 +1965,18 @@ get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored)) #endif static PyObject * -set_immortalize_deferred(PyObject *self, PyObject *value) +suppress_immortalization(PyObject *self, PyObject *value) { #ifdef Py_GIL_DISABLED - PyInterpreterState *interp = PyInterpreterState_Get(); - int old_enabled = interp->gc.immortalize.enabled; - int old_enabled_on_thread = interp->gc.immortalize.enable_on_thread_created; - int enabled_on_thread = 0; - if (!PyArg_ParseTuple(value, "i|i", - &interp->gc.immortalize.enabled, - &enabled_on_thread)) - { + int suppress = PyObject_IsTrue(value); + if (suppress < 0) { return NULL; } - interp->gc.immortalize.enable_on_thread_created = enabled_on_thread; - return Py_BuildValue("ii", old_enabled, old_enabled_on_thread); -#else - return Py_BuildValue("OO", Py_False, Py_False); + PyInterpreterState *interp = PyInterpreterState_Get(); + // Subtract two to suppress immortalization (so that 1 -> -1) + _Py_atomic_add_int(&interp->gc.immortalize, suppress ? -2 : 2); #endif + Py_RETURN_NONE; } static PyObject * @@ -1990,7 +1984,7 @@ get_immortalize_deferred(PyObject *self, PyObject *Py_UNUSED(ignored)) { #ifdef Py_GIL_DISABLED PyInterpreterState *interp = PyInterpreterState_Get(); - return PyBool_FromLong(interp->gc.immortalize.enable_on_thread_created); + return PyBool_FromLong(_Py_atomic_load_int(&interp->gc.immortalize) >= 0); #else Py_RETURN_FALSE; #endif @@ -2110,7 +2104,7 @@ static PyMethodDef module_functions[] = { #ifdef Py_GIL_DISABLED {"py_thread_id", get_py_thread_id, METH_NOARGS}, #endif - {"set_immortalize_deferred", set_immortalize_deferred, METH_VARARGS}, + {"suppress_immortalization", suppress_immortalization, METH_O}, {"get_immortalize_deferred", get_immortalize_deferred, METH_NOARGS}, #ifdef _Py_TIER2 {"uop_symbols_test", _Py_uop_symbols_test, METH_NOARGS}, |