summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-06-03 22:21:32 (GMT)
committerGitHub <noreply@github.com>2024-06-03 22:21:32 (GMT)
commitae705319fcde864b504987dc8e579e3eef68e1e5 (patch)
tree022166446a352d99b784b44a86f163bec179e94d /Modules
parentca37034baa2909722df58c02dfd13e1d667252ce (diff)
downloadcpython-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.c24
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},