summaryrefslogtreecommitdiffstats
path: root/Python/pystate.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-10-30 21:51:02 (GMT)
committerGitHub <noreply@github.com>2020-10-30 21:51:02 (GMT)
commiteba5bf2f5672bf4861c626937597b85ac0c242b9 (patch)
tree914219482fdbb19af1c54f1b6c9b81a67611c990 /Python/pystate.c
parent4fe72090deb7fb7bc09bfa56c92f6b3b0967d395 (diff)
downloadcpython-eba5bf2f5672bf4861c626937597b85ac0c242b9.zip
cpython-eba5bf2f5672bf4861c626937597b85ac0c242b9.tar.gz
cpython-eba5bf2f5672bf4861c626937597b85ac0c242b9.tar.bz2
bpo-42208: Call GC collect earlier in PyInterpreterState_Clear() (GH-23044)
The last GC collection is now done before clearing builtins and sys dictionaries. Add also assertions to ensure that gc.collect() is no longer called after _PyGC_Fini(). Pass also the tstate to PyInterpreterState_Clear() to pass the correct tstate to _PyGC_CollectNoFail() and _PyGC_Fini().
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index eb24f2b..e888986 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -268,14 +268,11 @@ out_of_memory:
}
-void
-PyInterpreterState_Clear(PyInterpreterState *interp)
+static void
+interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
{
_PyRuntimeState *runtime = interp->runtime;
- /* Use the current Python thread state to call audit hooks,
- not the current Python thread state of 'interp'. */
- PyThreadState *tstate = _PyThreadState_GET();
if (_PySys_Audit(tstate, "cpython.PyInterpreterState_Clear", NULL) < 0) {
_PyErr_Clear(tstate);
}
@@ -306,6 +303,12 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
if (_PyRuntimeState_GetFinalizing(runtime) == NULL) {
_PyWarnings_Fini(interp);
}
+
+ /* Last garbage collection on this interpreter */
+ _PyGC_CollectNoFail(tstate);
+
+ _PyGC_Fini(tstate);
+
/* We don't clear sysdict and builtins until the end of this function.
Because clearing other attributes can execute arbitrary Python code
which requires sysdict and builtins. */
@@ -320,6 +323,25 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
}
+void
+PyInterpreterState_Clear(PyInterpreterState *interp)
+{
+ // Use the current Python thread state to call audit hooks and to collect
+ // garbage. It can be different than the current Python thread state
+ // of 'interp'.
+ PyThreadState *current_tstate = _PyThreadState_GET();
+
+ interpreter_clear(interp, current_tstate);
+}
+
+
+void
+_PyInterpreterState_Clear(PyThreadState *tstate)
+{
+ interpreter_clear(tstate->interp, tstate);
+}
+
+
static void
zapthreads(PyInterpreterState *interp, int check_current)
{