diff options
author | Victor Stinner <vstinner@python.org> | 2020-10-30 21:51:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-30 21:51:02 (GMT) |
commit | eba5bf2f5672bf4861c626937597b85ac0c242b9 (patch) | |
tree | 914219482fdbb19af1c54f1b6c9b81a67611c990 /Python | |
parent | 4fe72090deb7fb7bc09bfa56c92f6b3b0967d395 (diff) | |
download | cpython-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')
-rw-r--r-- | Python/pylifecycle.c | 7 | ||||
-rw-r--r-- | Python/pystate.c | 32 |
2 files changed, 28 insertions, 11 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index adef161..ff58c1b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1576,10 +1576,7 @@ finalize_interp_clear(PyThreadState *tstate) int is_main_interp = _Py_IsMainInterpreter(tstate); /* Clear interpreter state and all thread states */ - PyInterpreterState_Clear(tstate->interp); - - /* Last explicit GC collection */ - _PyGC_CollectNoFail(tstate); + _PyInterpreterState_Clear(tstate); /* Clear all loghooks */ /* Both _PySys_Audit function and users still need PyObject, such as tuple. @@ -1588,8 +1585,6 @@ finalize_interp_clear(PyThreadState *tstate) _PySys_ClearAuditHooks(tstate); } - _PyGC_Fini(tstate); - if (is_main_interp) { _Py_HashRandomization_Fini(); _PyArg_Fini(); 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) { |