Skip to content

Commit

Permalink
bpo-38858: Add init_interp_main() subfunction (GH-17347)
Browse files Browse the repository at this point in the history
Fix new_interpreter() error handling: undo it all if status is an
exception.
  • Loading branch information
vstinner committed Nov 22, 2019
1 parent e0c9ab8 commit b005136
Showing 1 changed file with 109 additions and 103 deletions.
212 changes: 109 additions & 103 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, "
Expand All @@ -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 */
Expand Down Expand Up @@ -896,123 +898,115 @@ pyinit_core(_PyRuntimeState *runtime,
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");
}
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);
if (_PyStatus_EXCEPTION(status)) {
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();
Expand All @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand All @@ -1508,109 +1536,87 @@ 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;

PyObject *sysmod = _PyImport_FindBuiltin(tstate, "sys");
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 *
Expand Down

0 comments on commit b005136

Please sign in to comment.