Skip to content

bpo-38858: Add init_interp_main() subfunction #17347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 22, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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