From 43125224d6da5febb34101ebfd36536d791d68cd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 18:23:53 +0200 Subject: [PATCH] bpo-36710: Add runtime variable to Py_InitializeEx() (GH-12939) Py_InitializeEx() now uses a runtime variable passed to subfunctions, rather than working directly on the global variable _PyRuntime. Add 'runtime' parameter to _PyCoreConfig_Write(), _PySys_Create(), _PySys_InitMain(), _PyGILState_Init(), emit_stderr_warning_for_legacy_locale() and other subfunctions. --- Include/internal/pycore_coreconfig.h | 5 +- Include/internal/pycore_pylifecycle.h | 10 +- Python/coreconfig.c | 4 +- Python/pylifecycle.c | 130 +++++++++++++++----------- Python/pystate.c | 4 +- Python/sysmodule.c | 22 +++-- 6 files changed, 104 insertions(+), 71 deletions(-) diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index e88a46314c8..ac98e00159c 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pystate.h" /* _PyRuntimeState */ + /* --- _PyWstrList ------------------------------------------------ */ @@ -108,7 +110,8 @@ PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig( const _PyCoreConfig *config); PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args); -PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config); +PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config, + _PyRuntimeState *runtime); /* --- Function used for testing ---------------------------------- */ diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f07bc427bb8..69709b10b8f 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -34,10 +34,13 @@ extern _PyInitError _PyFaulthandler_Init(int enable); extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(void); extern _PyInitError _PySys_Create( + _PyRuntimeState *runtime, PyInterpreterState *interp, PyObject **sysmod_p); extern _PyInitError _PySys_SetPreliminaryStderr(PyObject *sysdict); -extern int _PySys_InitMain(PyInterpreterState *interp); +extern int _PySys_InitMain( + _PyRuntimeState *runtime, + PyInterpreterState *interp); extern _PyInitError _PyImport_Init(PyInterpreterState *interp); extern _PyInitError _PyExc_Init(void); extern _PyInitError _PyBuiltins_AddExceptions(PyObject * bltinmod); @@ -74,7 +77,10 @@ extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); -extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); +extern void _PyGILState_Init( + _PyRuntimeState *runtime, + PyInterpreterState *interp, + PyThreadState *tstate); extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 7b55b06b7a6..d05beef2aa5 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1605,13 +1605,13 @@ config_init_stdio(const _PyCoreConfig *config) - set Py_xxx global configuration variables - initialize C standard streams (stdin, stdout, stderr) */ void -_PyCoreConfig_Write(const _PyCoreConfig *config) +_PyCoreConfig_Write(const _PyCoreConfig *config, _PyRuntimeState *runtime) { _PyCoreConfig_SetGlobalConfig(config); config_init_stdio(config); /* Write the new pre-configuration into _PyRuntime */ - _PyPreConfig *preconfig = &_PyRuntime.preconfig; + _PyPreConfig *preconfig = &runtime->preconfig; preconfig->isolated = config->isolated; preconfig->use_environment = config->use_environment; preconfig->dev_mode = config->dev_mode; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index fe4cb97a474..03486c3b195 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -286,9 +286,9 @@ static const char *_C_LOCALE_WARNING = "locales is recommended.\n"; static void -_emit_stderr_warning_for_legacy_locale(void) +emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime) { - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; + const _PyPreConfig *preconfig = &runtime->preconfig; if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected()) { PySys_FormatStderr("%s", _C_LOCALE_WARNING); } @@ -468,7 +468,8 @@ _Py_SetLocaleFromEnv(int category) */ static _PyInitError -_Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, +_Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime, + PyInterpreterState **interp_p, const _PyCoreConfig *core_config) { PyThreadState *tstate = _PyThreadState_GET(); @@ -482,7 +483,7 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, } *interp_p = interp; - _PyCoreConfig_Write(core_config); + _PyCoreConfig_Write(core_config, runtime); if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { return _Py_INIT_NO_MEMORY(); @@ -500,18 +501,14 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, static _PyInitError -pycore_init_runtime(const _PyCoreConfig *core_config) +pycore_init_runtime(_PyRuntimeState *runtime, + const _PyCoreConfig *core_config) { - if (_PyRuntime.initialized) { + if (runtime->initialized) { return _Py_INIT_ERR("main interpreter already initialized"); } - _PyCoreConfig_Write(core_config); - - _PyInitError err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; - } + _PyCoreConfig_Write(core_config, runtime); /* Py_Finalize leaves _Py_Finalizing set in order to help daemon * threads behave a little more gracefully at interpreter shutdown. @@ -522,14 +519,14 @@ pycore_init_runtime(const _PyCoreConfig *core_config) * threads still hanging around from a previous Py_Initialize/Finalize * pair :( */ - _PyRuntime.finalizing = NULL; + runtime->finalizing = NULL; - err = _Py_HashRandomization_Init(core_config); + _PyInitError err = _Py_HashRandomization_Init(core_config); if (_Py_INIT_FAILED(err)) { return err; } - err = _PyInterpreterState_Enable(&_PyRuntime); + err = _PyInterpreterState_Enable(runtime); if (_Py_INIT_FAILED(err)) { return err; } @@ -538,7 +535,8 @@ pycore_init_runtime(const _PyCoreConfig *core_config) static _PyInitError -pycore_create_interpreter(const _PyCoreConfig *core_config, +pycore_create_interpreter(_PyRuntimeState *runtime, + const _PyCoreConfig *core_config, PyInterpreterState **interp_p) { PyInterpreterState *interp = PyInterpreterState_New(); @@ -565,7 +563,7 @@ pycore_create_interpreter(const _PyCoreConfig *core_config, _PyEval_FiniThreads(); /* Auto-thread-state API */ - _PyGILState_Init(interp, tstate); + _PyGILState_Init(runtime, interp, tstate); /* Create the GIL */ PyEval_InitThreads(); @@ -671,19 +669,20 @@ pycore_init_import_warnings(PyInterpreterState *interp, PyObject *sysmod) static _PyInitError -_Py_InitializeCore_impl(PyInterpreterState **interp_p, +_Py_InitializeCore_impl(_PyRuntimeState *runtime, + PyInterpreterState **interp_p, const _PyCoreConfig *core_config) { PyInterpreterState *interp; - _PyCoreConfig_Write(core_config); + _PyCoreConfig_Write(core_config, runtime); - _PyInitError err = pycore_init_runtime(core_config); + _PyInitError err = pycore_init_runtime(runtime, core_config); if (_Py_INIT_FAILED(err)) { return err; } - err = pycore_create_interpreter(core_config, &interp); + err = pycore_create_interpreter(runtime, core_config, &interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -696,7 +695,7 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p, } PyObject *sysmod; - err = _PySys_Create(interp, &sysmod); + err = _PySys_Create(runtime, interp, &sysmod); if (_Py_INIT_FAILED(err)) { return err; } @@ -712,7 +711,7 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p, } /* Only when we get here is the runtime core fully initialized */ - _PyRuntime.core_initialized = 1; + runtime->core_initialized = 1; return _Py_INIT_OK(); } @@ -726,8 +725,9 @@ preinit(const _PyPreConfig *src_config, const _PyArgv *args) if (_Py_INIT_FAILED(err)) { return err; } + _PyRuntimeState *runtime = &_PyRuntime; - if (_PyRuntime.pre_initialized) { + if (runtime->pre_initialized) { /* If it's already configured: ignored the new configuration */ return _Py_INIT_OK(); } @@ -751,7 +751,7 @@ preinit(const _PyPreConfig *src_config, const _PyArgv *args) goto done; } - _PyRuntime.pre_initialized = 1; + runtime->pre_initialized = 1; err = _Py_INIT_OK(); done: @@ -795,7 +795,8 @@ _Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig) static _PyInitError -pyinit_coreconfig(_PyCoreConfig *config, +pyinit_coreconfig(_PyRuntimeState *runtime, + _PyCoreConfig *config, const _PyCoreConfig *src_config, const _PyArgv *args, PyInterpreterState **interp_p) @@ -811,11 +812,11 @@ pyinit_coreconfig(_PyCoreConfig *config, return err; } - if (!_PyRuntime.core_initialized) { - return _Py_InitializeCore_impl(interp_p, config); + if (!runtime->core_initialized) { + return _Py_InitializeCore_impl(runtime, interp_p, config); } else { - return _Py_Initialize_ReconfigureCore(interp_p, config); + return _Py_Initialize_ReconfigureCore(runtime, interp_p, config); } } @@ -838,7 +839,8 @@ pyinit_coreconfig(_PyCoreConfig *config, * safe to call without calling Py_Initialize first) */ static _PyInitError -_Py_InitializeCore(const _PyCoreConfig *src_config, +_Py_InitializeCore(_PyRuntimeState *runtime, + const _PyCoreConfig *src_config, const _PyArgv *args, PyInterpreterState **interp_p) { @@ -855,7 +857,7 @@ _Py_InitializeCore(const _PyCoreConfig *src_config, } _PyCoreConfig local_config = _PyCoreConfig_INIT; - err = pyinit_coreconfig(&local_config, src_config, args, interp_p); + err = pyinit_coreconfig(runtime, &local_config, src_config, args, interp_p); _PyCoreConfig_Clear(&local_config); return err; } @@ -894,16 +896,17 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp) * non-zero return code. */ static _PyInitError -_Py_InitializeMainInterpreter(PyInterpreterState *interp) +_Py_InitializeMainInterpreter(_PyRuntimeState *runtime, + PyInterpreterState *interp) { - if (!_PyRuntime.core_initialized) { + if (!runtime->core_initialized) { return _Py_INIT_ERR("runtime core not initialized"); } /* Configure the main interpreter */ _PyCoreConfig *core_config = &interp->core_config; - if (_PyRuntime.initialized) { + if (runtime->initialized) { return _Py_ReconfigureMainInterpreter(interp); } @@ -913,7 +916,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) * This means anything which needs support from extension modules * or pure Python code in the standard library won't work. */ - _PyRuntime.initialized = 1; + runtime->initialized = 1; return _Py_INIT_OK(); } @@ -921,7 +924,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) return _Py_INIT_ERR("can't initialize time"); } - if (_PySys_InitMain(interp) < 0) { + if (_PySys_InitMain(runtime, interp) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); } @@ -974,7 +977,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) Py_XDECREF(warnings_module); } - _PyRuntime.initialized = 1; + runtime->initialized = 1; if (core_config->site_import) { err = initsite(); /* Module site */ @@ -984,7 +987,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) } #ifndef MS_WINDOWS - _emit_stderr_warning_for_legacy_locale(); + emit_stderr_warning_for_legacy_locale(runtime); #endif return _Py_INIT_OK(); @@ -995,16 +998,23 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) static _PyInitError init_python(const _PyCoreConfig *config, const _PyArgv *args) { - PyInterpreterState *interp = NULL; _PyInitError err; - err = _Py_InitializeCore(config, args, &interp); + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + PyInterpreterState *interp = NULL; + err = _Py_InitializeCore(runtime, config, args, &interp); if (_Py_INIT_FAILED(err)) { return err; } config = &interp->core_config; if (config->_init_main) { - err = _Py_InitializeMainInterpreter(interp); + err = _Py_InitializeMainInterpreter(runtime, interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1040,7 +1050,15 @@ _Py_InitializeFromConfig(const _PyCoreConfig *config) void Py_InitializeEx(int install_sigs) { - if (_PyRuntime.initialized) { + _PyInitError err; + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + _Py_ExitInitError(err); + } + _PyRuntimeState *runtime = &_PyRuntime; + + if (runtime->initialized) { /* bpo-33932: Calling Py_Initialize() twice does nothing. */ return; } @@ -1048,7 +1066,7 @@ Py_InitializeEx(int install_sigs) _PyCoreConfig config = _PyCoreConfig_INIT; config.install_signal_handlers = install_sigs; - _PyInitError err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } @@ -1364,12 +1382,15 @@ Py_Finalize(void) static _PyInitError new_interpreter(PyThreadState **tstate_p) { - PyInterpreterState *interp; - PyThreadState *tstate, *save_tstate; - PyObject *bimod, *sysmod; _PyInitError err; - if (!_PyRuntime.initialized) { + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + if (!runtime->initialized) { return _Py_INIT_ERR("Py_Initialize must be called first"); } @@ -1377,20 +1398,20 @@ new_interpreter(PyThreadState **tstate_p) interpreters: disable PyGILState_Check(). */ _PyGILState_check_enabled = 0; - interp = PyInterpreterState_New(); + PyInterpreterState *interp = PyInterpreterState_New(); if (interp == NULL) { *tstate_p = NULL; return _Py_INIT_OK(); } - tstate = PyThreadState_New(interp); + PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) { PyInterpreterState_Delete(interp); *tstate_p = NULL; return _Py_INIT_OK(); } - save_tstate = PyThreadState_Swap(tstate); + PyThreadState *save_tstate = PyThreadState_Swap(tstate); /* Copy the current interpreter config into the new interpreter */ _PyCoreConfig *core_config; @@ -1419,14 +1440,15 @@ new_interpreter(PyThreadState **tstate_p) } interp->modules = modules; - sysmod = _PyImport_FindBuiltin("sys", modules); + PyObject *sysmod = _PyImport_FindBuiltin("sys", modules); if (sysmod != NULL) { interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) + if (interp->sysdict == NULL) { goto handle_error; + } Py_INCREF(interp->sysdict); PyDict_SetItemString(interp->sysdict, "modules", modules); - if (_PySys_InitMain(interp) < 0) { + if (_PySys_InitMain(runtime, interp) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); } } @@ -1434,7 +1456,7 @@ new_interpreter(PyThreadState **tstate_p) goto handle_error; } - bimod = _PyImport_FindBuiltin("builtins", modules); + PyObject *bimod = _PyImport_FindBuiltin("builtins", modules); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) diff --git a/Python/pystate.c b/Python/pystate.c index 498a9546e1b..a413f9d7ab4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1052,13 +1052,13 @@ PyThreadState_IsCurrent(PyThreadState *tstate) Py_Initialize/Py_FinalizeEx */ void -_PyGILState_Init(PyInterpreterState *interp, PyThreadState *tstate) +_PyGILState_Init(_PyRuntimeState *runtime, + PyInterpreterState *interp, PyThreadState *tstate) { /* must init with valid states */ assert(interp != NULL); assert(tstate != NULL); - _PyRuntimeState *runtime = &_PyRuntime; struct _gilstate_runtime_state *gilstate = &runtime->gilstate; if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3de94e8468b..0f7af2c69da 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2155,12 +2155,12 @@ static PyStructSequence_Desc flags_desc = { }; static PyObject* -make_flags(void) +make_flags(_PyRuntimeState *runtime, PyInterpreterState *interp) { int pos = 0; PyObject *seq; - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - const _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + const _PyPreConfig *preconfig = &runtime->preconfig; + const _PyCoreConfig *config = &interp->core_config; seq = PyStructSequence_New(&FlagsType); if (seq == NULL) @@ -2375,7 +2375,8 @@ static struct PyModuleDef sysmodule = { } while (0) static _PyInitError -_PySys_InitCore(PyObject *sysdict) +_PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp, + PyObject *sysdict) { PyObject *version_info; int res; @@ -2465,8 +2466,8 @@ _PySys_InitCore(PyObject *sysdict) goto type_init_failed; } } - /* Set flags to their default values */ - SET_SYS_FROM_STRING("flags", make_flags()); + /* Set flags to their default values (updated by _PySys_InitMain()) */ + SET_SYS_FROM_STRING("flags", make_flags(runtime, interp)); #if defined(MS_WINDOWS) /* getwindowsversion */ @@ -2587,7 +2588,7 @@ sys_create_xoptions_dict(const _PyCoreConfig *config) int -_PySys_InitMain(PyInterpreterState *interp) +_PySys_InitMain(_PyRuntimeState *runtime, PyInterpreterState *interp) { PyObject *sysdict = interp->sysdict; const _PyCoreConfig *config = &interp->core_config; @@ -2641,7 +2642,7 @@ _PySys_InitMain(PyInterpreterState *interp) #undef SET_SYS_FROM_WSTR /* Set flags to their final values */ - SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags()); + SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags(runtime, interp)); /* prevent user from creating new instances */ FlagsType.tp_init = NULL; FlagsType.tp_new = NULL; @@ -2708,7 +2709,8 @@ error: /* Create sys module without all attributes: _PySys_InitMain() should be called later to add remaining attributes. */ _PyInitError -_PySys_Create(PyInterpreterState *interp, PyObject **sysmod_p) +_PySys_Create(_PyRuntimeState *runtime, PyInterpreterState *interp, + PyObject **sysmod_p) { PyObject *modules = PyDict_New(); if (modules == NULL) { @@ -2737,7 +2739,7 @@ _PySys_Create(PyInterpreterState *interp, PyObject **sysmod_p) return err; } - err = _PySys_InitCore(sysdict); + err = _PySys_InitCore(runtime, interp, sysdict); if (_Py_INIT_FAILED(err)) { return err; }