diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-08-05 12:31:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-05 12:31:59 +0200 |
commit | 0c90d6f75931da4fec84d06c2efe9dd94bb96b77 (patch) | |
tree | ec34949a2d8b022b854acb0e885552c8fc0dd5ff /Python/pylifecycle.c | |
parent | e65ec491fbaa14db61a6559eb269733616b0e7f0 (diff) | |
download | cpython-git-0c90d6f75931da4fec84d06c2efe9dd94bb96b77.tar.gz |
[3.7] bpo-34247: Fix Python 3.7 initialization (#8659)
* -X dev: it is now possible to override the memory allocator using
PYTHONMALLOC even if the developer mode is enabled.
* Add _Py_InitializeFromConfig()
* Add _Py_Initialize_ReadEnvVars() to set global configuration
variables from environment variables
* Fix the code to initialize Python: Py_Initialize() now also reads
environment variables
* _Py_InitializeCore() can now be called twice: the second call
only replaces the configuration.
* Write unit tests on Py_Initialize() and the different ways to
configure Python
* The isolated mode now always sets Py_IgnoreEnvironmentFlag and
Py_NoUserSiteDirectory to 1.
* pymain_read_conf() now saves/restores the configuration
if the encoding changed
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 156 |
1 files changed, 110 insertions, 46 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 219a465588..f75b8604a3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -576,6 +576,27 @@ _Py_SetLocaleFromEnv(int category) */ +static _PyInitError +_Py_Initialize_ReconfigureCore(PyInterpreterState *interp, + const _PyCoreConfig *core_config) +{ + if (core_config->allocator != NULL) { + const char *allocator = _PyMem_GetAllocatorsName(); + if (allocator == NULL || strcmp(core_config->allocator, allocator) != 0) { + return _Py_INIT_USER_ERR("cannot modify memory allocator " + "after first Py_Initialize()"); + } + } + + _PyCoreConfig_SetGlobalConfig(core_config); + + if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { + return _Py_INIT_ERR("failed to copy core config"); + } + return _Py_INIT_OK(); +} + + /* Begin interpreter initialization * * On return, the first thread and interpreter state have been created, @@ -595,15 +616,32 @@ _Py_SetLocaleFromEnv(int category) */ _PyInitError -_Py_InitializeCore(const _PyCoreConfig *core_config) +_Py_InitializeCore_impl(PyInterpreterState **interp_p, + const _PyCoreConfig *core_config) { - assert(core_config != NULL); - PyInterpreterState *interp; - PyThreadState *tstate; - PyObject *bimod, *sysmod, *pstderr; _PyInitError err; + /* bpo-34008: For backward compatibility reasons, calling Py_Main() after + Py_Initialize() ignores the new configuration. */ + if (_PyRuntime.core_initialized) { + PyThreadState *tstate = PyThreadState_GET(); + if (!tstate) { + return _Py_INIT_ERR("no thread state found"); + } + + interp = tstate->interp; + if (interp == NULL) { + return _Py_INIT_ERR("no main interpreter found"); + } + *interp_p = interp; + + return _Py_Initialize_ReconfigureCore(interp, core_config); + } + + + _PyCoreConfig_SetGlobalConfig(core_config); + err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(err)) { return err; @@ -660,12 +698,13 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) if (interp == NULL) { return _Py_INIT_ERR("can't make main interpreter"); } + *interp_p = interp; if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { return _Py_INIT_ERR("failed to copy core config"); } - tstate = PyThreadState_New(interp); + PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) return _Py_INIT_ERR("can't make first thread"); (void) PyThreadState_Swap(tstate); @@ -702,6 +741,7 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) return _Py_INIT_ERR("can't make modules dictionary"); interp->modules = modules; + PyObject *sysmod; err = _PySys_BeginInit(&sysmod); if (_Py_INIT_FAILED(err)) { return err; @@ -723,7 +763,7 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) if (_PyStructSequence_Init() < 0) return _Py_INIT_ERR("can't initialize structseq"); - bimod = _PyBuiltin_Init(); + PyObject *bimod = _PyBuiltin_Init(); if (bimod == NULL) return _Py_INIT_ERR("can't initialize builtins modules"); _PyImport_FixupBuiltin(bimod, "builtins", modules); @@ -737,7 +777,7 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) /* Set up a preliminary stderr printer until we have enough infrastructure for the io module in place. */ - pstderr = PyFile_NewStdPrinter(fileno(stderr)); + PyObject *pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) return _Py_INIT_ERR("can't set preliminary stderr"); _PySys_SetObjectId(&PyId_stderr, pstderr); @@ -775,6 +815,43 @@ _Py_InitializeCore(const _PyCoreConfig *core_config) return _Py_INIT_OK(); } + +_PyInitError +_Py_InitializeCore(PyInterpreterState **interp_p, + const _PyCoreConfig *src_config) +{ + assert(src_config != NULL); + + PyMemAllocatorEx old_alloc; + _PyInitError err; + + /* Copy the configuration, since _PyCoreConfig_Read() modifies it + (and the input configuration is read only). */ + _PyCoreConfig config = _PyCoreConfig_INIT; + + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + if (_PyCoreConfig_Copy(&config, src_config) >= 0) { + err = _PyCoreConfig_Read(&config); + } + else { + err = _Py_INIT_ERR("failed to copy core config"); + } + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_INIT_FAILED(err)) { + goto done; + } + + err = _Py_InitializeCore_impl(interp_p, &config); + +done: + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + _PyCoreConfig_Clear(&config); + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + return err; +} + /* Py_Initialize() has already been called: update the main interpreter configuration. Example of bpo-34008: Py_Main() called after Py_Initialize(). */ @@ -803,24 +880,15 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp, * non-zero return code. */ _PyInitError -_Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) +_Py_InitializeMainInterpreter(PyInterpreterState *interp, + const _PyMainInterpreterConfig *config) { - PyInterpreterState *interp; - PyThreadState *tstate; _PyInitError err; if (!_PyRuntime.core_initialized) { return _Py_INIT_ERR("runtime core not initialized"); } - /* Get current thread state and interpreter pointer */ - tstate = PyThreadState_GET(); - if (!tstate) - return _Py_INIT_ERR("failed to read thread state"); - interp = tstate->interp; - if (!interp) - return _Py_INIT_ERR("failed to get interpreter"); - /* Now finish configuring the main interpreter */ if (_PyMainInterpreterConfig_Copy(&interp->config, config) < 0) { return _Py_INIT_ERR("failed to copy main interpreter config"); @@ -909,53 +977,49 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) #undef _INIT_DEBUG_PRINT + _PyInitError -_Py_InitializeEx_Private(int install_sigs, int install_importlib) +_Py_InitializeFromConfig(const _PyCoreConfig *config) { - if (_PyRuntime.initialized) { - /* bpo-33932: Calling Py_Initialize() twice does nothing. */ - return _Py_INIT_OK(); - } + _Py_Initialize_ReadEnvVarsNoAlloc(); - _PyCoreConfig config = _PyCoreConfig_INIT; + PyInterpreterState *interp; _PyInitError err; - - config.ignore_environment = Py_IgnoreEnvironmentFlag; - config._disable_importlib = !install_importlib; - config.install_signal_handlers = install_sigs; - - err = _PyCoreConfig_Read(&config); + err = _Py_InitializeCore(&interp, config); if (_Py_INIT_FAILED(err)) { - goto done; - } - - err = _Py_InitializeCore(&config); - if (_Py_INIT_FAILED(err)) { - goto done; + return err; } + config = &interp->core_config; _PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT; - err = _PyMainInterpreterConfig_Read(&main_config, &config); + err = _PyMainInterpreterConfig_Read(&main_config, config); if (!_Py_INIT_FAILED(err)) { - err = _Py_InitializeMainInterpreter(&main_config); + err = _Py_InitializeMainInterpreter(interp, &main_config); } _PyMainInterpreterConfig_Clear(&main_config); if (_Py_INIT_FAILED(err)) { - goto done; + return err; } - err = _Py_INIT_OK(); - -done: - _PyCoreConfig_Clear(&config); - return err; + return _Py_INIT_OK(); } void Py_InitializeEx(int install_sigs) { - _PyInitError err = _Py_InitializeEx_Private(install_sigs, 1); + if (_PyRuntime.initialized) { + /* bpo-33932: Calling Py_Initialize() twice does nothing. */ + return; + } + + _PyInitError err; + _PyCoreConfig config = _PyCoreConfig_INIT; + config.install_signal_handlers = install_sigs; + + err = _Py_InitializeFromConfig(&config); + _PyCoreConfig_Clear(&config); + if (_Py_INIT_FAILED(err)) { _Py_FatalInitError(err); } |