summaryrefslogtreecommitdiff
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2020-12-27 12:46:59 -0500
committerJason R. Coombs <jaraco@jaraco.com>2020-12-27 12:46:59 -0500
commita78f0158a28734f965218b834ea8c0b166b7353f (patch)
treedca70268e2a41d49658e7eed783c6fc243d119cd /Python/pylifecycle.c
parentec8e6895a3ce9cd69b6ceb75a15fcc74d4a522dc (diff)
parentbf64d9064ab641b1ef9a0c4bda097ebf1204faf4 (diff)
downloadcpython-git-revert-23107-revert-13893-fix-issue-37193.tar.gz
Merge branch 'master' into revert-23107-revert-13893-fix-issue-37193revert-23107-revert-13893-fix-issue-37193
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r--Python/pylifecycle.c381
1 files changed, 173 insertions, 208 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index ff58c1b915..9828dffad5 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -8,6 +8,7 @@
#include "pycore_ceval.h" // _PyEval_FiniGIL()
#include "pycore_context.h" // _PyContext_Init()
#include "pycore_fileutils.h" // _Py_ResetForceASCII()
+#include "pycore_import.h" // _PyImport_BootstrapImp()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_object.h" // _PyDebug_PrintTotalRefs()
#include "pycore_pathconfig.h" // _PyConfig_WritePathConfig()
@@ -54,8 +55,6 @@ static PyStatus add_main_module(PyInterpreterState *interp);
static PyStatus init_import_site(void);
static PyStatus init_set_builtins_open(void);
static PyStatus init_sys_streams(PyThreadState *tstate);
-static PyStatus init_signals(PyThreadState *tstate);
-static void call_py_exitfuncs(PyThreadState *tstate);
static void wait_for_thread_shutdown(PyThreadState *tstate);
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
@@ -97,14 +96,6 @@ _Py_IsFinalizing(void)
int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
PyOS_mystrnicmp; /* Python/pystrcmp.o */
-/* PyModule_GetWarningsModule is no longer necessary as of 2.6
-since _warnings is builtin. This API should not be used. */
-PyObject *
-PyModule_GetWarningsModule(void)
-{
- return PyImport_ImportModule("warnings");
-}
-
/* APIs to access the initialization flags
*
@@ -135,59 +126,54 @@ Py_IsInitialized(void)
having the lock, but you cannot use multiple threads.)
*/
-
-static PyStatus
+static int
init_importlib(PyThreadState *tstate, PyObject *sysmod)
{
- PyObject *importlib;
- PyObject *impmod;
- PyObject *value;
+ assert(!_PyErr_Occurred(tstate));
+
PyInterpreterState *interp = tstate->interp;
int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
- /* Import _importlib through its frozen version, _frozen_importlib. */
- if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
- return _PyStatus_ERR("can't import _frozen_importlib");
- }
- else if (verbose) {
+ // Import _importlib through its frozen version, _frozen_importlib.
+ if (verbose) {
PySys_FormatStderr("import _frozen_importlib # frozen\n");
}
- importlib = PyImport_AddModule("_frozen_importlib");
+ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
+ return -1;
+ }
+ PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
if (importlib == NULL) {
- return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules");
+ return -1;
}
- interp->importlib = importlib;
- Py_INCREF(interp->importlib);
-
- interp->import_func = _PyDict_GetItemStringWithError(interp->builtins, "__import__");
- if (interp->import_func == NULL)
- return _PyStatus_ERR("__import__ not found");
- Py_INCREF(interp->import_func);
+ interp->importlib = Py_NewRef(importlib);
- /* Import the _imp module */
- impmod = PyInit__imp();
- if (impmod == NULL) {
- return _PyStatus_ERR("can't import _imp");
- }
- else if (verbose) {
+ // Import the _imp module
+ if (verbose) {
PySys_FormatStderr("import _imp # builtin\n");
}
- if (_PyImport_SetModuleString("_imp", impmod) < 0) {
- return _PyStatus_ERR("can't save _imp to sys.modules");
+ PyObject *imp_mod = _PyImport_BootstrapImp(tstate);
+ if (imp_mod == NULL) {
+ return -1;
+ }
+ if (_PyImport_SetModuleString("_imp", imp_mod) < 0) {
+ Py_DECREF(imp_mod);
+ return -1;
}
- /* Install importlib as the implementation of import */
- value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
+ // Install importlib as the implementation of import
+ PyObject *value = PyObject_CallMethod(importlib, "_install",
+ "OO", sysmod, imp_mod);
+ Py_DECREF(imp_mod);
if (value == NULL) {
- _PyErr_Print(tstate);
- return _PyStatus_ERR("importlib install failed");
+ return -1;
}
Py_DECREF(value);
- Py_DECREF(impmod);
- return _PyStatus_OK();
+ assert(!_PyErr_Occurred(tstate));
+ return 0;
}
+
static PyStatus
init_importlib_external(PyThreadState *tstate)
{
@@ -428,6 +414,69 @@ _Py_SetLocaleFromEnv(int category)
}
+static int
+interpreter_update_config(PyThreadState *tstate, int only_update_path_config)
+{
+ const PyConfig *config = &tstate->interp->config;
+
+ if (!only_update_path_config) {
+ PyStatus status = _PyConfig_Write(config, tstate->interp->runtime);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ return -1;
+ }
+ }
+
+ if (_Py_IsMainInterpreter(tstate)) {
+ PyStatus status = _PyConfig_WritePathConfig(config);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ return -1;
+ }
+ }
+
+ // Update the sys module for the new configuration
+ if (_PySys_UpdateConfig(tstate) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
+int
+_PyInterpreterState_SetConfig(const PyConfig *src_config)
+{
+ PyThreadState *tstate = PyThreadState_Get();
+ int res = -1;
+
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ PyStatus status = _PyConfig_Copy(&config, src_config);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ goto done;
+ }
+
+ status = PyConfig_Read(&config);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ goto done;
+ }
+
+ status = _PyConfig_Copy(&tstate->interp->config, &config);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ goto done;
+ }
+
+ res = interpreter_update_config(tstate, 0);
+
+done:
+ PyConfig_Clear(&config);
+ return res;
+}
+
+
/* Global initializations. Can be undone by Py_Finalize(). Don't
call this twice without an intervening Py_Finalize() call.
@@ -462,7 +511,7 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime,
return status;
}
- status = _PyInterpreterState_SetConfig(interp, config);
+ status = _PyConfig_Copy(&interp->config, config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
@@ -550,7 +599,7 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
return _PyStatus_ERR("can't make main interpreter");
}
- PyStatus status = _PyInterpreterState_SetConfig(interp, config);
+ PyStatus status = _PyConfig_Copy(&interp->config, config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
@@ -637,6 +686,15 @@ pycore_init_types(PyThreadState *tstate)
}
}
+ if (_PyWarnings_InitState(tstate) < 0) {
+ return _PyStatus_ERR("can't initialize warnings");
+ }
+
+ status = _PyAtExit_Init(tstate);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+
return _PyStatus_OK();
}
@@ -674,6 +732,14 @@ pycore_init_builtins(PyThreadState *tstate)
}
Py_DECREF(bimod);
+ // Get the __import__ function
+ PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,
+ "__import__");
+ if (import_func == NULL) {
+ goto error;
+ }
+ interp->import_func = Py_NewRef(import_func);
+
assert(!_PyErr_Occurred(tstate));
return _PyStatus_OK();
@@ -685,44 +751,6 @@ error:
static PyStatus
-pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
-{
- assert(!_PyErr_Occurred(tstate));
-
- PyStatus status = _PyImportHooks_Init(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- /* Initialize _warnings. */
- status = _PyWarnings_InitState(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
- if (config->_install_importlib) {
- if (_Py_IsMainInterpreter(tstate)) {
- status = _PyConfig_WritePathConfig(config);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- }
-
- /* This call sets up builtin and frozen import support */
- status = init_importlib(tstate, sysmod);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- }
-
- assert(!_PyErr_Occurred(tstate));
-
- return _PyStatus_OK();
-}
-
-
-static PyStatus
pycore_interp_init(PyThreadState *tstate)
{
PyStatus status;
@@ -743,7 +771,13 @@ pycore_interp_init(PyThreadState *tstate)
goto done;
}
- status = pycore_init_import_warnings(tstate, sysmod);
+ const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
+ if (config->_install_importlib) {
+ /* This call sets up builtin and frozen import support */
+ if (init_importlib(tstate, sysmod) < 0) {
+ return _PyStatus_ERR("failed to initialize importlib");
+ }
+ }
done:
/* sys.modules['sys'] contains a strong reference to the module */
@@ -917,14 +951,16 @@ pyinit_core(_PyRuntimeState *runtime,
}
PyConfig config;
- _PyConfig_InitCompatConfig(&config);
+ PyConfig_InitPythonConfig(&config);
status = _PyConfig_Copy(&config, src_config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
- status = PyConfig_Read(&config);
+ // Read the configuration, but don't compute the path configuration
+ // (it is computed in the main init).
+ status = _PyConfig_Read(&config, 0);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
@@ -949,19 +985,10 @@ done:
configuration. Example of bpo-34008: Py_Main() called after
Py_Initialize(). */
static PyStatus
-_Py_ReconfigureMainInterpreter(PyThreadState *tstate)
+pyinit_main_reconfigure(PyThreadState *tstate)
{
- const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
-
- PyObject *argv = _PyWideStringList_AsList(&config->argv);
- if (argv == NULL) {
- return _PyStatus_NO_MEMORY(); \
- }
-
- int res = PyDict_SetItemString(tstate->interp->sysdict, "argv", argv);
- Py_DECREF(argv);
- if (res < 0) {
- return _PyStatus_ERR("fail to set sys.argv");
+ if (interpreter_update_config(tstate, 0) < 0) {
+ return _PyStatus_ERR("fail to reconfigure Python");
}
return _PyStatus_OK();
}
@@ -989,14 +1016,14 @@ init_interp_main(PyThreadState *tstate)
return _PyStatus_OK();
}
- if (is_main_interp) {
- if (_PyTime_Init() < 0) {
- return _PyStatus_ERR("can't initialize time");
- }
+ // Compute the path configuration
+ status = _PyConfig_InitPathConfig(&interp->config, 1);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
}
- if (_PySys_InitMain(tstate) < 0) {
- return _PyStatus_ERR("can't finish initializing sys");
+ if (interpreter_update_config(tstate, 1) < 0) {
+ return _PyStatus_ERR("failed to update the Python config");
}
status = init_importlib_external(tstate);
@@ -1018,11 +1045,8 @@ init_interp_main(PyThreadState *tstate)
}
if (is_main_interp) {
- if (config->install_signal_handlers) {
- status = init_signals(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
+ if (_PySignal_Init(config->install_signal_handlers) < 0) {
+ return _PyStatus_ERR("can't initialize signals");
}
if (_PyTraceMalloc_Init(config->tracemalloc) < 0) {
@@ -1100,7 +1124,7 @@ pyinit_main(PyThreadState *tstate)
}
if (interp->runtime->initialized) {
- return _Py_ReconfigureMainInterpreter(tstate);
+ return pyinit_main_reconfigure(tstate);
}
PyStatus status = init_interp_main(tstate);
@@ -1112,19 +1136,6 @@ pyinit_main(PyThreadState *tstate)
PyStatus
-_Py_InitializeMain(void)
-{
- PyStatus status = _PyRuntime_Initialize();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- _PyRuntimeState *runtime = &_PyRuntime;
- PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
- return pyinit_main(tstate);
-}
-
-
-PyStatus
Py_InitializeFromConfig(const PyConfig *config)
{
if (config == NULL) {
@@ -1191,6 +1202,19 @@ Py_Initialize(void)
}
+PyStatus
+_Py_InitializeMain(void)
+{
+ PyStatus status = _PyRuntime_Initialize();
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+ _PyRuntimeState *runtime = &_PyRuntime;
+ PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
+ return pyinit_main(tstate);
+}
+
+
static void
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
{
@@ -1545,16 +1569,13 @@ flush_std_files(void)
static void
finalize_interp_types(PyThreadState *tstate)
{
- // The _ast module state is shared by all interpreters.
- // The state must only be cleared by the main interpreter.
- if (_Py_IsMainInterpreter(tstate)) {
- _PyAST_Fini(tstate);
- }
-
_PyExc_Fini(tstate);
_PyFrame_Fini(tstate);
_PyAsyncGen_Fini(tstate);
_PyContext_Fini(tstate);
+ _PyType_Fini(tstate);
+ // Call _PyUnicode_ClearInterned() before _PyDict_Fini() since it uses
+ // a dict internally.
_PyUnicode_ClearInterned(tstate);
_PyDict_Fini(tstate);
@@ -1591,8 +1612,6 @@ finalize_interp_clear(PyThreadState *tstate)
_Py_ClearFileSystemEncoding();
}
- _PyWarnings_Fini(tstate->interp);
-
finalize_interp_types(tstate);
}
@@ -1627,7 +1646,6 @@ Py_FinalizeEx(void)
/* Get current thread state and interpreter pointer */
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
- PyInterpreterState *interp = tstate->interp;
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
@@ -1645,18 +1663,18 @@ Py_FinalizeEx(void)
* the threads created via Threading.
*/
- call_py_exitfuncs(tstate);
+ _PyAtExit_Call(tstate);
/* Copy the core config, PyInterpreterState_Delete() free
the core config memory */
#ifdef Py_REF_DEBUG
- int show_ref_count = interp->config.show_ref_count;
+ int show_ref_count = tstate->interp->config.show_ref_count;
#endif
#ifdef Py_TRACE_REFS
- int dump_refs = interp->config.dump_refs;
+ int dump_refs = tstate->interp->config.dump_refs;
#endif
#ifdef WITH_PYMALLOC
- int malloc_stats = interp->config.malloc_stats;
+ int malloc_stats = tstate->interp->config.malloc_stats;
#endif
/* Remaining daemon threads will automatically exit
@@ -1681,7 +1699,7 @@ Py_FinalizeEx(void)
}
/* Disable signal handling */
- PyOS_FiniInterrupts();
+ _PySignal_Fini();
/* Collect garbage. This may call finalizers; it's nice to call these
* before all modules are destroyed.
@@ -1734,9 +1752,6 @@ Py_FinalizeEx(void)
/* Destroy the database used by _PyImport_{Fixup,Find}Extension */
_PyImport_Fini();
- /* Cleanup typeobject.c's internal caches. */
- _PyType_Fini();
-
/* unload faulthandler module */
_PyFaulthandler_Fini();
@@ -1852,7 +1867,8 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter)
config = _PyInterpreterState_GetConfig(main_interp);
}
- status = _PyInterpreterState_SetConfig(interp, config);
+
+ status = _PyConfig_Copy(&interp->config, config);
if (_PyStatus_EXCEPTION(status)) {
goto error;
}
@@ -1935,7 +1951,7 @@ Py_EndInterpreter(PyThreadState *tstate)
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
- call_py_exitfuncs(tstate);
+ _PyAtExit_Call(tstate);
if (tstate != interp->tstate_head || tstate->next != NULL) {
Py_FatalError("not the last thread");
@@ -2621,30 +2637,6 @@ Py_ExitStatusException(PyStatus status)
}
}
-/* Clean up and exit */
-
-/* For the atexit module. */
-void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module)
-{
- PyInterpreterState *is = _PyInterpreterState_GET();
-
- /* Guard against API misuse (see bpo-17852) */
- assert(is->pyexitfunc == NULL || is->pyexitfunc == func);
-
- is->pyexitfunc = func;
- is->pyexitmodule = module;
-}
-
-static void
-call_py_exitfuncs(PyThreadState *tstate)
-{
- PyInterpreterState *interp = tstate->interp;
- if (interp->pyexitfunc == NULL)
- return;
-
- (*interp->pyexitfunc)(interp->pyexitmodule);
- _PyErr_Clear(tstate);
-}
/* Wait until threading._shutdown completes, provided
the threading module was imported in the first place.
@@ -2708,48 +2700,6 @@ Py_Exit(int sts)
exit(sts);
}
-static PyStatus
-init_signals(PyThreadState *tstate)
-{
-#ifdef SIGPIPE
- PyOS_setsig(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGXFZ
- PyOS_setsig(SIGXFZ, SIG_IGN);
-#endif
-#ifdef SIGXFSZ
- PyOS_setsig(SIGXFSZ, SIG_IGN);
-#endif
- PyOS_InitInterrupts(); /* May imply init_signals() */
- if (_PyErr_Occurred(tstate)) {
- return _PyStatus_ERR("can't import signal");
- }
- return _PyStatus_OK();
-}
-
-
-/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
- *
- * All of the code in this function must only use async-signal-safe functions,
- * listed at `man 7 signal` or
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
- *
- * If this function is updated, update also _posix_spawn() of subprocess.py.
- */
-void
-_Py_RestoreSignals(void)
-{
-#ifdef SIGPIPE
- PyOS_setsig(SIGPIPE, SIG_DFL);
-#endif
-#ifdef SIGXFZ
- PyOS_setsig(SIGXFZ, SIG_DFL);
-#endif
-#ifdef SIGXFSZ
- PyOS_setsig(SIGXFSZ, SIG_DFL);
-#endif
-}
-
/*
* The file descriptor fd is considered ``interactive'' if either
@@ -2770,6 +2720,21 @@ Py_FdIsInteractive(FILE *fp, const char *filename)
}
+int
+_Py_FdIsInteractive(FILE *fp, PyObject *filename)
+{
+ if (isatty((int)fileno(fp))) {
+ return 1;
+ }
+ if (!Py_InteractiveFlag) {
+ return 0;
+ }
+ return (filename == NULL) ||
+ (PyUnicode_CompareWithASCIIString(filename, "<stdin>") == 0) ||
+ (PyUnicode_CompareWithASCIIString(filename, "???") == 0);
+}
+
+
/* Wrappers around sigaction() or signal(). */
PyOS_sighandler_t