summaryrefslogtreecommitdiffstats
path: root/Python/pystate.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-24 15:32:26 (GMT)
committerGitHub <noreply@github.com>2020-03-24 15:32:26 (GMT)
commit5804f878e779712e803be927ca8a6df389d82cdf (patch)
tree393bdef0f05d253739d2a0335391541cb482fc26 /Python/pystate.c
parent472fc843ca816d65c12f9508ac762ca492165c45 (diff)
downloadcpython-5804f878e779712e803be927ca8a6df389d82cdf.zip
cpython-5804f878e779712e803be927ca8a6df389d82cdf.tar.gz
cpython-5804f878e779712e803be927ca8a6df389d82cdf.tar.bz2
bpo-20526: Fix PyThreadState_Clear(): don't decref frame (GH-19120)
PyThreadState.frame is a borrowed reference, not a strong reference: PyThreadState_Clear() must not call Py_CLEAR(tstate->frame). Remove test_threading.test_warnings_at_exit(): we cannot warranty that the Python thread state of daemon threads is cleared in a reliable way during Python shutdown.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 6331a85..8f0b6b8 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -765,11 +765,19 @@ PyThreadState_Clear(PyThreadState *tstate)
{
int verbose = tstate->interp->config.verbose;
- if (verbose && tstate->frame != NULL)
+ if (verbose && tstate->frame != NULL) {
+ /* bpo-20526: After the main thread calls
+ _PyRuntimeState_SetFinalizing() in Py_FinalizeEx(), threads must
+ exit when trying to take the GIL. If a thread exit in the middle of
+ _PyEval_EvalFrameDefault(), tstate->frame is not reset to its
+ previous value. It is more likely with daemon threads, but it can
+ happen with regular threads if threading._shutdown() fails
+ (ex: interrupted by CTRL+C). */
fprintf(stderr,
"PyThreadState_Clear: warning: thread still has a frame\n");
+ }
- Py_CLEAR(tstate->frame);
+ /* Don't clear tstate->frame: it is a borrowed reference */
Py_CLEAR(tstate->dict);
Py_CLEAR(tstate->async_exc);