diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2020-12-27 12:46:59 -0500 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2020-12-27 12:46:59 -0500 |
commit | a78f0158a28734f965218b834ea8c0b166b7353f (patch) | |
tree | dca70268e2a41d49658e7eed783c6fc243d119cd /Python/pylifecycle.c | |
parent | ec8e6895a3ce9cd69b6ceb75a15fcc74d4a522dc (diff) | |
parent | bf64d9064ab641b1ef9a0c4bda097ebf1204faf4 (diff) | |
download | cpython-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.c | 381 |
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 |