]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38858: Add init_interp_main() subfunction (GH-17347)
authorVictor Stinner <vstinner@python.org>
Fri, 22 Nov 2019 16:52:42 +0000 (17:52 +0100)
committerGitHub <noreply@github.com>
Fri, 22 Nov 2019 16:52:42 +0000 (17:52 +0100)
Fix new_interpreter() error handling: undo it all if status is an
exception.

Python/pylifecycle.c

index 4825b8b28e621b3032f26992273562d3f6b67520..e692d75999d6b7c625ddd174761f94f24ce9d0de 100644 (file)
@@ -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 *