diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/_warnings.c | 2 | ||||
-rw-r--r-- | Python/ceval_gil.c | 3 | ||||
-rw-r--r-- | Python/pylifecycle.c | 17 | ||||
-rw-r--r-- | Python/pystate.c | 12 | ||||
-rw-r--r-- | Python/sysmodule.c | 4 |
5 files changed, 32 insertions, 6 deletions
diff --git a/Python/_warnings.c b/Python/_warnings.c index 5644db9..dec6586 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -198,7 +198,7 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import) PyObject *warnings_module, *obj; /* don't try to import after the start of the Python finallization */ - if (try_import && !_Py_IsFinalizing()) { + if (try_import && !_Py_IsInterpreterFinalizing(interp)) { warnings_module = PyImport_Import(&_Py_ID(warnings)); if (warnings_module == NULL) { /* Fallback to the C implementation if we cannot get diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 42e1436..b9bdb74 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -332,6 +332,9 @@ tstate_must_exit(PyThreadState *tstate) After Py_Finalize() has been called, tstate can be a dangling pointer: point to PyThreadState freed memory. */ PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + if (finalizing == NULL) { + finalizing = _PyInterpreterState_GetFinalizing(tstate->interp); + } return (finalizing != NULL && finalizing != tstate); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c5dc0f4..cb87f2c 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1788,6 +1788,7 @@ Py_FinalizeEx(void) /* Remaining daemon threads will automatically exit when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ + _PyInterpreterState_SetFinalizing(tstate->interp, tstate); _PyRuntimeState_SetFinalizing(runtime, tstate); runtime->initialized = 0; runtime->core_initialized = 0; @@ -2142,6 +2143,10 @@ Py_EndInterpreter(PyThreadState *tstate) Py_FatalError("not the last thread"); } + /* Remaining daemon threads will automatically exit + when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ + _PyInterpreterState_SetFinalizing(interp, tstate); + // XXX Call something like _PyImport_Disable() here? _PyImport_FiniExternal(tstate->interp); @@ -2152,6 +2157,18 @@ Py_EndInterpreter(PyThreadState *tstate) finalize_interp_delete(tstate->interp); } +int +_Py_IsInterpreterFinalizing(PyInterpreterState *interp) +{ + /* We check the runtime first since, in a daemon thread, + interp might be dangling pointer. */ + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + if (finalizing == NULL) { + finalizing = _PyInterpreterState_GetFinalizing(interp); + } + return finalizing != NULL; +} + /* Add the __main__ module */ static PyStatus diff --git a/Python/pystate.c b/Python/pystate.c index 26debf1..25e655a 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1436,11 +1436,13 @@ PyThreadState_Clear(PyThreadState *tstate) if (verbose && tstate->cframe->current_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 + _PyInterpreterState_SetFinalizing() in Py_FinalizeEx() + (or in Py_EndInterpreter() for subinterpreters), + 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"); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 894a3e8..c116c40 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -332,6 +332,7 @@ _PySys_ClearAuditHooks(PyThreadState *ts) } _PyRuntimeState *runtime = ts->interp->runtime; + /* The hooks are global so we have to check for runtime finalization. */ PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); assert(finalizing == ts); if (finalizing != ts) { @@ -2039,6 +2040,9 @@ sys__clear_type_cache_impl(PyObject *module) Py_RETURN_NONE; } +/* Note that, for now, we do not have a per-interpreter equivalent + for sys.is_finalizing(). */ + /*[clinic input] sys.is_finalizing |