summaryrefslogtreecommitdiffstats
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2019-11-22 16:52:42 (GMT)
committerGitHub <noreply@github.com>2019-11-22 16:52:42 (GMT)
commitb00513636c9891deba4cae50217e25e8faf6c6ac (patch)
treecb89f289edeb47e66cf5cb33c6ede6fd05ac8a98 /Python/pylifecycle.c
parente0c9ab8e26d1648b870b80c296b2490a5e9553e5 (diff)
downloadcpython-b00513636c9891deba4cae50217e25e8faf6c6ac.zip
cpython-b00513636c9891deba4cae50217e25e8faf6c6ac.tar.gz
cpython-b00513636c9891deba4cae50217e25e8faf6c6ac.tar.bz2
bpo-38858: Add init_interp_main() subfunction (GH-17347)
Fix new_interpreter() error handling: undo it all if status is an exception.
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r--Python/pylifecycle.c212
1 files changed, 109 insertions, 103 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 4825b8b..e692d75 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -260,6 +260,7 @@ _Py_LegacyLocaleDetected(int warn)
#endif
}
+#ifndef MS_WINDOWS
static const char *_C_LOCALE_WARNING =
"Python runtime initialized with LC_CTYPE=C (a locale with default ASCII "
"encoding), which may cause Unicode compatibility problems. Using C.UTF-8, "
@@ -274,6 +275,7 @@ emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime)
PySys_FormatStderr("%s", _C_LOCALE_WARNING);
}
}
+#endif /* !defined(MS_WINDOWS) */
typedef struct _CandidateLocale {
const char *locale_name; /* The locale to try as a coercion target */
@@ -896,16 +898,16 @@ done:
configuration. Example of bpo-34008: Py_Main() called after
Py_Initialize(). */
static PyStatus
-_Py_ReconfigureMainInterpreter(PyInterpreterState *interp)
+_Py_ReconfigureMainInterpreter(PyThreadState *tstate)
{
- PyConfig *config = &interp->config;
+ PyConfig *config = &tstate->interp->config;
PyObject *argv = _PyWideStringList_AsList(&config->argv);
if (argv == NULL) {
return _PyStatus_NO_MEMORY(); \
}
- int res = PyDict_SetItemString(interp->sysdict, "argv", argv);
+ int res = PyDict_SetItemString(tstate->interp->sysdict, "argv", argv);
Py_DECREF(argv);
if (res < 0) {
return _PyStatus_ERR("fail to set sys.argv");
@@ -913,60 +915,48 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp)
return _PyStatus_OK();
}
-/* Update interpreter state based on supplied configuration settings
- *
- * After calling this function, most of the restrictions on the interpreter
- * are lifted. The only remaining incomplete settings are those related
- * to the main module (sys.argv[0], __main__ metadata)
- *
- * Calling this when the interpreter is not initializing, is already
- * initialized or without a valid current thread state is a fatal error.
- * Other errors should be reported as normal Python exceptions with a
- * non-zero return code.
- */
+
static PyStatus
-pyinit_main(PyThreadState *tstate)
+init_interp_main(PyThreadState *tstate)
{
- _PyRuntimeState *runtime = tstate->interp->runtime;
- if (!runtime->core_initialized) {
- return _PyStatus_ERR("runtime core not initialized");
- }
-
- /* Configure the main interpreter */
+ PyStatus status;
+ int is_main_interp = _Py_IsMainInterpreter(tstate);
PyInterpreterState *interp = tstate->interp;
PyConfig *config = &interp->config;
- if (runtime->initialized) {
- return _Py_ReconfigureMainInterpreter(interp);
- }
-
if (!config->_install_importlib) {
/* Special mode for freeze_importlib: run with no import system
*
* This means anything which needs support from extension modules
* or pure Python code in the standard library won't work.
*/
- runtime->initialized = 1;
+ if (is_main_interp) {
+ interp->runtime->initialized = 1;
+ }
return _PyStatus_OK();
}
- if (_PyTime_Init() < 0) {
- return _PyStatus_ERR("can't initialize time");
- }
+ if (is_main_interp) {
+ if (_PyTime_Init() < 0) {
+ return _PyStatus_ERR("can't initialize time");
+ }
- if (_PySys_InitMain(tstate) < 0) {
- return _PyStatus_ERR("can't finish initializing sys");
+ if (_PySys_InitMain(tstate) < 0) {
+ return _PyStatus_ERR("can't finish initializing sys");
+ }
}
- PyStatus status = init_importlib_external(tstate);
+ status = init_importlib_external(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- /* initialize the faulthandler module */
- status = _PyFaulthandler_Init(config->faulthandler);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
+ if (is_main_interp) {
+ /* initialize the faulthandler module */
+ status = _PyFaulthandler_Init(config->faulthandler);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
}
status = _PyUnicode_InitEncodings(tstate);
@@ -974,45 +964,49 @@ pyinit_main(PyThreadState *tstate)
return status;
}
- if (config->install_signal_handlers) {
- status = init_signals(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
+ if (is_main_interp) {
+ if (config->install_signal_handlers) {
+ status = init_signals(tstate);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
}
- }
- if (_PyTraceMalloc_Init(config->tracemalloc) < 0) {
- return _PyStatus_ERR("can't initialize tracemalloc");
+ if (_PyTraceMalloc_Init(config->tracemalloc) < 0) {
+ return _PyStatus_ERR("can't initialize tracemalloc");
+ }
}
- status = add_main_module(interp);
+ status = init_sys_streams(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- status = init_sys_streams(tstate);
+ status = init_set_builtins_open(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- status = init_set_builtins_open(tstate);
+ status = add_main_module(interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- /* Initialize warnings. */
- PyObject *warnoptions = PySys_GetObject("warnoptions");
- if (warnoptions != NULL && PyList_Size(warnoptions) > 0)
- {
- PyObject *warnings_module = PyImport_ImportModule("warnings");
- if (warnings_module == NULL) {
- fprintf(stderr, "'import warnings' failed; traceback:\n");
- _PyErr_Print(tstate);
+ if (is_main_interp) {
+ /* Initialize warnings. */
+ PyObject *warnoptions = PySys_GetObject("warnoptions");
+ if (warnoptions != NULL && PyList_Size(warnoptions) > 0)
+ {
+ PyObject *warnings_module = PyImport_ImportModule("warnings");
+ if (warnings_module == NULL) {
+ fprintf(stderr, "'import warnings' failed; traceback:\n");
+ _PyErr_Print(tstate);
+ }
+ Py_XDECREF(warnings_module);
}
- Py_XDECREF(warnings_module);
- }
- runtime->initialized = 1;
+ interp->runtime->initialized = 1;
+ }
if (config->site_import) {
status = init_import_site();
@@ -1021,14 +1015,47 @@ pyinit_main(PyThreadState *tstate)
}
}
+ if (is_main_interp) {
#ifndef MS_WINDOWS
- emit_stderr_warning_for_legacy_locale(runtime);
+ emit_stderr_warning_for_legacy_locale(interp->runtime);
#endif
+ }
return _PyStatus_OK();
}
+/* Update interpreter state based on supplied configuration settings
+ *
+ * After calling this function, most of the restrictions on the interpreter
+ * are lifted. The only remaining incomplete settings are those related
+ * to the main module (sys.argv[0], __main__ metadata)
+ *
+ * Calling this when the interpreter is not initializing, is already
+ * initialized or without a valid current thread state is a fatal error.
+ * Other errors should be reported as normal Python exceptions with a
+ * non-zero return code.
+ */
+static PyStatus
+pyinit_main(PyThreadState *tstate)
+{
+ PyInterpreterState *interp = tstate->interp;
+ if (!interp->runtime->core_initialized) {
+ return _PyStatus_ERR("runtime core not initialized");
+ }
+
+ if (interp->runtime->initialized) {
+ return _Py_ReconfigureMainInterpreter(tstate);
+ }
+
+ PyStatus status = init_interp_main(tstate);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+ return _PyStatus_OK();
+}
+
+
PyStatus
_Py_InitializeMain(void)
{
@@ -1440,6 +1467,7 @@ Py_Finalize(void)
Py_FinalizeEx();
}
+
/* Create and initialize a new interpreter and thread, and return the
new thread. This requires that Py_Initialize() has been called
first.
@@ -1499,7 +1527,7 @@ new_interpreter(PyThreadState **tstate_p)
status = _PyConfig_Copy(&interp->config, config);
if (_PyStatus_EXCEPTION(status)) {
- return status;
+ goto done;
}
config = &interp->config;
@@ -1508,7 +1536,8 @@ new_interpreter(PyThreadState **tstate_p)
/* XXX The following is lax in error checking */
PyObject *modules = PyDict_New();
if (modules == NULL) {
- return _PyStatus_ERR("can't make modules dictionary");
+ status = _PyStatus_ERR("can't make modules dictionary");
+ goto done;
}
interp->modules = modules;
@@ -1516,101 +1545,78 @@ new_interpreter(PyThreadState **tstate_p)
if (sysmod != NULL) {
interp->sysdict = PyModule_GetDict(sysmod);
if (interp->sysdict == NULL) {
- goto handle_error;
+ goto handle_exc;
}
Py_INCREF(interp->sysdict);
PyDict_SetItemString(interp->sysdict, "modules", modules);
if (_PySys_InitMain(tstate) < 0) {
- return _PyStatus_ERR("can't finish initializing sys");
+ status = _PyStatus_ERR("can't finish initializing sys");
+ goto done;
}
}
else if (_PyErr_Occurred(tstate)) {
- goto handle_error;
+ goto handle_exc;
}
PyObject *bimod = _PyImport_FindBuiltin(tstate, "builtins");
if (bimod != NULL) {
interp->builtins = PyModule_GetDict(bimod);
if (interp->builtins == NULL)
- goto handle_error;
+ goto handle_exc;
Py_INCREF(interp->builtins);
}
else if (_PyErr_Occurred(tstate)) {
- goto handle_error;
+ goto handle_exc;
}
if (bimod != NULL && sysmod != NULL) {
status = _PyBuiltins_AddExceptions(bimod);
if (_PyStatus_EXCEPTION(status)) {
- return status;
+ goto done;
}
status = _PySys_SetPreliminaryStderr(interp->sysdict);
if (_PyStatus_EXCEPTION(status)) {
- return status;
+ goto done;
}
status = _PyImportHooks_Init(tstate);
if (_PyStatus_EXCEPTION(status)) {
- return status;
+ goto done;
}
status = init_importlib(tstate, sysmod);
if (_PyStatus_EXCEPTION(status)) {
- return status;
+ goto done;
}
- status = init_importlib_external(tstate);
+ status = init_interp_main(tstate);
if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- status = _PyUnicode_InitEncodings(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- status = init_sys_streams(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- status = init_set_builtins_open(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- status = add_main_module(interp);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- if (config->site_import) {
- status = init_import_site();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
+ goto done;
}
}
if (_PyErr_Occurred(tstate)) {
- goto handle_error;
+ goto handle_exc;
}
*tstate_p = tstate;
return _PyStatus_OK();
-handle_error:
- /* Oops, it didn't work. Undo it all. */
+handle_exc:
+ status = _PyStatus_OK();
+done:
+ *tstate_p = NULL;
+
+ /* Oops, it didn't work. Undo it all. */
PyErr_PrintEx(0);
PyThreadState_Clear(tstate);
PyThreadState_Delete(tstate);
PyInterpreterState_Delete(interp);
PyThreadState_Swap(save_tstate);
- *tstate_p = NULL;
- return _PyStatus_OK();
+ return status;
}
PyThreadState *