summaryrefslogtreecommitdiffstats
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r--Python/pylifecycle.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 5ef2d3f..a8a8e7f 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -696,10 +696,11 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
init_interp_settings(interp, &config);
- PyThreadState *tstate = PyThreadState_New(interp);
+ PyThreadState *tstate = _PyThreadState_New(interp);
if (tstate == NULL) {
return _PyStatus_ERR("can't make first thread");
}
+ _PyThreadState_Bind(tstate);
(void) PyThreadState_Swap(tstate);
status = init_interp_create_gil(tstate);
@@ -1821,6 +1822,11 @@ Py_FinalizeEx(void)
/* Get current thread state and interpreter pointer */
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
+ // XXX assert(_Py_IsMainInterpreter(tstate->interp));
+ // XXX assert(_Py_IsMainThread());
+
+ // Block some operations.
+ tstate->interp->finalizing = 1;
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
@@ -1867,7 +1873,23 @@ Py_FinalizeEx(void)
_PyRuntimeState_SetFinalizing() has been called, no other Python thread
can take the GIL at this point: if they try, they will exit
immediately. */
- _PyThreadState_DeleteExcept(runtime, tstate);
+ _PyThreadState_DeleteExcept(tstate);
+
+ /* At this point no Python code should be running at all.
+ The only thread state left should be the main thread of the main
+ interpreter (AKA tstate), in which this code is running right now.
+ There may be other OS threads running but none of them will have
+ thread states associated with them, nor will be able to create
+ new thread states.
+
+ Thus tstate is the only possible thread state from here on out.
+ It may still be used during finalization to run Python code as
+ needed or provide runtime state (e.g. sys.modules) but that will
+ happen sparingly. Furthermore, the order of finalization aims
+ to not need a thread (or interpreter) state as soon as possible.
+ */
+ // XXX Make sure we are preventing the creating of any new thread states
+ // (or interpreters).
/* Flush sys.stdout and sys.stderr */
if (flush_std_files() < 0) {
@@ -1958,6 +1980,20 @@ Py_FinalizeEx(void)
}
#endif /* Py_TRACE_REFS */
+ /* At this point there's almost no other Python code that will run,
+ nor interpreter state needed. The only possibility is the
+ finalizers of the objects stored on tstate (and tstate->interp),
+ which are triggered via finalize_interp_clear().
+
+ For now we operate as though none of those finalizers actually
+ need an operational thread state or interpreter. In reality,
+ those finalizers may rely on some part of tstate or
+ tstate->interp, and/or may raise exceptions
+ or otherwise fail.
+ */
+ // XXX Do this sooner during finalization.
+ // XXX Ensure finalizer errors are handled properly.
+
finalize_interp_clear(tstate);
finalize_interp_delete(tstate->interp);
@@ -2039,12 +2075,13 @@ new_interpreter(PyThreadState **tstate_p, const _PyInterpreterConfig *config)
return _PyStatus_OK();
}
- PyThreadState *tstate = PyThreadState_New(interp);
+ PyThreadState *tstate = _PyThreadState_New(interp);
if (tstate == NULL) {
PyInterpreterState_Delete(interp);
*tstate_p = NULL;
return _PyStatus_OK();
}
+ _PyThreadState_Bind(tstate);
PyThreadState *save_tstate = PyThreadState_Swap(tstate);