From 70005ac0fddd8585725b92acd1bc2b8e7b81999c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 15:25:34 -0400 Subject: bpo-36763: _PyCoreConfig_SetPyArgv() preinitializes Python (GH-13037) _PyCoreConfig_SetPyArgv() and _PyCoreConfig_SetWideString() now pre-initialize Python if needed to ensure that the locale encoding is properly configured. * Add _Py_PreInitializeFromPyArgv() internal function. * Add 'args' parameter to _Py_PreInitializeFromCoreConfig() --- Include/internal/pycore_pylifecycle.h | 9 +++++++-- Modules/main.c | 9 +-------- Python/coreconfig.c | 31 +++++++++++++++++++++++++++++-- Python/pylifecycle.c | 28 +++++++++++++--------------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 321cc5d..adb1f5d 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -8,7 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_pystate.h" /* _PyRuntimeState */ +#include "pycore_coreconfig.h" /* _PyArgv */ +#include "pycore_pystate.h" /* _PyRuntimeState */ /* True if the main interpreter thread exited due to an unhandled * KeyboardInterrupt exception, suggesting the user pressed ^C. */ @@ -90,8 +91,12 @@ extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(_PyRuntimeState *runtime); +PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPyArgv( + const _PyPreConfig *src_config, + const _PyArgv *args); PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig( - const _PyCoreConfig *coreconfig); + const _PyCoreConfig *coreconfig, + const _PyArgv *args); #ifdef __cplusplus } diff --git a/Modules/main.c b/Modules/main.c index 575683c..e117ef2 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -57,14 +57,7 @@ pymain_init(const _PyArgv *args) environment variables (PYTHONUTF8 and PYTHONCOERCECLOCALE) */ preconfig.coerce_c_locale = -1; preconfig.utf8_mode = -1; - if (args->use_bytes_argv) { - err = _Py_PreInitializeFromArgs(&preconfig, - args->argc, args->bytes_argv); - } - else { - err = _Py_PreInitializeFromWideArgs(&preconfig, - args->argc, args->wchar_argv); - } + err = _Py_PreInitializeFromPyArgv(&preconfig, args); if (_Py_INIT_FAILED(err)) { return err; } diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 15643be..5202694 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -541,11 +541,15 @@ _PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) } -/* Decode str using Py_DecodeLocale() and set the result into *config_str */ static _PyInitError _PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, const char *decode_err_msg) { + _PyInitError err = _Py_PreInitialize(NULL); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *str2; if (str != NULL) { size_t len; @@ -572,6 +576,9 @@ _PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, _PyCoreConfig_DecodeLocaleErr(config_str, str, "cannot decode " NAME) +/* Decode str using Py_DecodeLocale() and set the result into *config_str. + Pre-initialize Python if needed to ensure that encodings are properly + configured. */ _PyInitError _PyCoreConfig_DecodeLocale(wchar_t **config_str, const char *str) { @@ -2100,10 +2107,30 @@ done: _PyInitError _PyCoreConfig_SetPyArgv(_PyCoreConfig *config, const _PyArgv *args) { + if (args->use_bytes_argv) { + _PyInitError err; + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + /* do nothing if Python is already pre-initialized: + _PyCoreConfig_Write() will update _PyRuntime.preconfig later */ + if (!runtime->pre_initialized) { + err = _Py_PreInitializeFromCoreConfig(config, args); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + } return _PyArgv_AsWstrList(args, &config->argv); } +/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python + if needed to ensure that encodings are properly configured. */ _PyInitError _PyCoreConfig_SetArgv(_PyCoreConfig *config, int argc, char **argv) { @@ -2138,7 +2165,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) { _PyInitError err; - err = _Py_PreInitializeFromCoreConfig(config); + err = _Py_PreInitializeFromCoreConfig(config, NULL); if (_Py_INIT_FAILED(err)) { return err; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2a633cf..2ba43b9 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -683,8 +683,8 @@ _Py_InitializeCore_impl(_PyRuntimeState *runtime, } -static _PyInitError -preinit(const _PyPreConfig *src_config, const _PyArgv *args) +_PyInitError +_Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) { _PyInitError err; @@ -726,11 +726,12 @@ done: return err; } + _PyInitError _Py_PreInitializeFromArgs(const _PyPreConfig *src_config, int argc, char **argv) { _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv}; - return preinit(src_config, &args); + return _Py_PreInitializeFromPyArgv(src_config, &args); } @@ -738,24 +739,26 @@ _PyInitError _Py_PreInitializeFromWideArgs(const _PyPreConfig *src_config, int argc, wchar_t **argv) { _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv}; - return preinit(src_config, &args); + return _Py_PreInitializeFromPyArgv(src_config, &args); } _PyInitError _Py_PreInitialize(const _PyPreConfig *src_config) { - return preinit(src_config, NULL); + return _Py_PreInitializeFromPyArgv(src_config, NULL); } _PyInitError -_Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig) +_Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, + const _PyArgv *args) { - assert(coreconfig != NULL); _PyPreConfig config = _PyPreConfig_INIT; - _PyCoreConfig_GetCoreConfig(&config, coreconfig); - return _Py_PreInitialize(&config); + if (coreconfig != NULL) { + _PyCoreConfig_GetCoreConfig(&config, coreconfig); + } + return _Py_PreInitializeFromPyArgv(&config, args); /* No need to clear config: _PyCoreConfig_GetCoreConfig() doesn't allocate memory */ } @@ -823,12 +826,7 @@ _Py_InitializeCore(_PyRuntimeState *runtime, { _PyInitError err; - if (src_config) { - err = _Py_PreInitializeFromCoreConfig(src_config); - } - else { - err = _Py_PreInitialize(NULL); - } + err = _Py_PreInitializeFromCoreConfig(src_config, args); if (_Py_INIT_FAILED(err)) { return err; } -- cgit v0.12