diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-05-20 09:02:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-20 09:02:00 (GMT) |
commit | 6d1c46746e17367caf8a24623cb5c9a9c4e3e036 (patch) | |
tree | 17ea108a38c01e32ec2d3a25df03bd47968af7ff /Python | |
parent | 6d965b39b7a486dd9e96a60b19ee92382d668299 (diff) | |
download | cpython-6d1c46746e17367caf8a24623cb5c9a9c4e3e036.zip cpython-6d1c46746e17367caf8a24623cb5c9a9c4e3e036.tar.gz cpython-6d1c46746e17367caf8a24623cb5c9a9c4e3e036.tar.bz2 |
bpo-36763: Fix Python preinitialization (GH-13432)
* Add _PyPreConfig.parse_argv
* Add _PyCoreConfig._config_init field and _PyCoreConfigInitEnum enum
type
* Initialization functions: reject preconfig=NULL and config=NULL
* Add config parameter to _PyCoreConfig_DecodeLocaleErr(): pass
config->argv to _Py_PreInitializeFromPyArgv(), to parse config
command line arguments in preinitialization.
* Add config parameter to _PyCoreConfig_SetString(). It now
preinitializes Python.
* _PyCoreConfig_SetPyArgv() now also preinitializes Python for wide
argv
* Fix _Py_PreInitializeFromCoreConfig(): don't pass args to
_Py_PreInitializeFromPyArgv() if config.parse_argv=0.
* Use "char * const *" and "wchar_t * const *" types for 'argv'
parameters and _PyArgv.argv.
* Add unit test on preinitialization from argv.
* _PyPreConfig.allocator type becomes int
* Add _PyPreConfig_InitFromPreConfig() and
_PyPreConfig_InitFromCoreConfig() helper functions
Diffstat (limited to 'Python')
-rw-r--r-- | Python/coreconfig.c | 123 | ||||
-rw-r--r-- | Python/preconfig.c | 80 | ||||
-rw-r--r-- | Python/pylifecycle.c | 57 |
3 files changed, 152 insertions, 108 deletions
diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 470bda8..958845e 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -551,6 +551,7 @@ _PyCoreConfig_Init(_PyCoreConfig *config) memset(config, 0, sizeof(*config)); config->_config_version = _Py_CONFIG_VERSION; + config->_config_init = (int)_PyCoreConfig_INIT; config->isolated = -1; config->use_environment = -1; config->dev_mode = -1; @@ -612,6 +613,7 @@ _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config) { _PyCoreConfig_InitDefaults(config); + config->_config_init = (int)_PyCoreConfig_INIT_PYTHON; config->configure_c_stdio = 1; config->parse_argv = 1; @@ -624,6 +626,7 @@ _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config) { _PyCoreConfig_InitDefaults(config); + config->_config_init = (int)_PyCoreConfig_INIT_ISOLATED; config->isolated = 1; config->use_environment = 0; config->user_site_directory = 0; @@ -643,8 +646,14 @@ _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config) /* Copy str into *config_str (duplicate the string) */ _PyInitError -_PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) +_PyCoreConfig_SetString(_PyCoreConfig *config, wchar_t **config_str, + const wchar_t *str) { + _PyInitError err = _Py_PreInitializeFromCoreConfig(config, NULL); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *str2; if (str != NULL) { str2 = _PyMem_RawWcsdup(str); @@ -662,10 +671,10 @@ _PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) static _PyInitError -_PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, - const char *decode_err_msg) +_PyCoreConfig_DecodeLocaleErr(_PyCoreConfig *config, wchar_t **config_str, + const char *str, const char *decode_err_msg) { - _PyInitError err = _Py_PreInitialize(NULL); + _PyInitError err = _Py_PreInitializeFromCoreConfig(config, NULL); if (_Py_INIT_FAILED(err)) { return err; } @@ -692,17 +701,18 @@ _PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, } -#define CONFIG_DECODE_LOCALE(config_str, str, NAME) \ - _PyCoreConfig_DecodeLocaleErr(config_str, str, "cannot decode " NAME) +#define CONFIG_DECODE_LOCALE(config, config_str, str, NAME) \ + _PyCoreConfig_DecodeLocaleErr(config, 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) +_PyCoreConfig_DecodeLocale(_PyCoreConfig *config, wchar_t **config_str, + const char *str) { - return CONFIG_DECODE_LOCALE(config_str, str, "string"); + return CONFIG_DECODE_LOCALE(config, config_str, str, "string"); } @@ -715,7 +725,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR #define COPY_WSTR_ATTR(ATTR) \ do { \ - err = _PyCoreConfig_SetString(&config->ATTR, config2->ATTR); \ + err = _PyCoreConfig_SetString(config, &config->ATTR, config2->ATTR); \ if (_Py_INIT_FAILED(err)) { \ return err; \ } \ @@ -727,6 +737,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } \ } while (0) + COPY_ATTR(_config_init); COPY_ATTR(isolated); COPY_ATTR(use_environment); COPY_ATTR(dev_mode); @@ -829,6 +840,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) #define SET_ITEM_WSTRLIST(LIST) \ SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) + SET_ITEM_INT(_config_init); SET_ITEM_INT(isolated); SET_ITEM_INT(use_environment); SET_ITEM_INT(dev_mode); @@ -910,7 +922,7 @@ _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) Return 0 on success, but *dest can be NULL. Return -1 on memory allocation failure. Return -2 on decoding error. */ static _PyInitError -_PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, +_PyCoreConfig_GetEnvDup(_PyCoreConfig *config, wchar_t **dest, wchar_t *wname, char *name, const char *decode_err_msg) @@ -930,7 +942,7 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, return _Py_INIT_OK(); } - return _PyCoreConfig_SetString(dest, var); + return _PyCoreConfig_SetString(config, dest, var); #else const char *var = getenv(name); if (!var || var[0] == '\0') { @@ -938,7 +950,7 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, return _Py_INIT_OK(); } - return _PyCoreConfig_DecodeLocaleErr(dest, var, decode_err_msg); + return _PyCoreConfig_DecodeLocaleErr(config, dest, var, decode_err_msg); #endif } @@ -1053,7 +1065,7 @@ config_init_program_name(_PyCoreConfig *config) script. */ const char *p = _PyCoreConfig_GetEnv(config, "PYTHONEXECUTABLE"); if (p != NULL) { - err = CONFIG_DECODE_LOCALE(&config->program_name, p, + err = CONFIG_DECODE_LOCALE(config, &config->program_name, p, "PYTHONEXECUTABLE environment variable"); if (_Py_INIT_FAILED(err)) { return err; @@ -1067,7 +1079,8 @@ config_init_program_name(_PyCoreConfig *config) /* Used by Mac/Tools/pythonw.c to forward * the argv0 of the stub executable */ - err = CONFIG_DECODE_LOCALE(&config->program_name, pyvenv_launcher, + err = CONFIG_DECODE_LOCALE(config, + &config->program_name, pyvenv_launcher, "__PYVENV_LAUNCHER__ environment variable"); if (_Py_INIT_FAILED(err)) { return err; @@ -1094,7 +1107,8 @@ config_init_program_name(_PyCoreConfig *config) #else const wchar_t *default_program_name = L"python3"; #endif - err = _PyCoreConfig_SetString(&config->program_name, default_program_name); + err = _PyCoreConfig_SetString(config, &config->program_name, + default_program_name); if (_Py_INIT_FAILED(err)) { return err; } @@ -1109,7 +1123,8 @@ config_init_executable(_PyCoreConfig *config) /* If Py_SetProgramFullPath() was called, use its value */ const wchar_t *program_full_path = _Py_path_config.program_full_path; if (program_full_path != NULL) { - _PyInitError err = _PyCoreConfig_SetString(&config->executable, + _PyInitError err = _PyCoreConfig_SetString(config, + &config->executable, program_full_path); if (_Py_INIT_FAILED(err)) { return err; @@ -1135,7 +1150,7 @@ config_init_home(_PyCoreConfig *config) /* If Py_SetPythonHome() was called, use its value */ wchar_t *home = _Py_path_config.home; if (home) { - _PyInitError err = _PyCoreConfig_SetString(&config->home, home); + _PyInitError err = _PyCoreConfig_SetString(config, &config->home, home); if (_Py_INIT_FAILED(err)) { return err; } @@ -1392,14 +1407,14 @@ config_get_stdio_errors(const _PyCoreConfig *config) static _PyInitError -config_get_locale_encoding(wchar_t **locale_encoding) +config_get_locale_encoding(_PyCoreConfig *config, wchar_t **locale_encoding) { #ifdef MS_WINDOWS char encoding[20]; PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); - return _PyCoreConfig_DecodeLocale(locale_encoding, encoding); + return _PyCoreConfig_DecodeLocale(config, locale_encoding, encoding); #elif defined(_Py_FORCE_UTF8_LOCALE) - return _PyCoreConfig_SetString(locale_encoding, L"utf-8"); + return _PyCoreConfig_SetString(config, locale_encoding, L"utf-8"); #else const char *encoding = nl_langinfo(CODESET); if (!encoding || encoding[0] == '\0') { @@ -1407,7 +1422,8 @@ config_get_locale_encoding(wchar_t **locale_encoding) "nl_langinfo(CODESET) failed"); } /* nl_langinfo(CODESET) is decoded by Py_DecodeLocale() */ - return CONFIG_DECODE_LOCALE(locale_encoding, encoding, + return CONFIG_DECODE_LOCALE(config, + locale_encoding, encoding, "nl_langinfo(CODESET)"); #endif } @@ -1422,7 +1438,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* If Py_SetStandardStreamEncoding() have been called, use these parameters. */ if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { - err = CONFIG_DECODE_LOCALE(&config->stdio_encoding, + err = CONFIG_DECODE_LOCALE(config, &config->stdio_encoding, _Py_StandardStreamEncoding, "_Py_StandardStreamEncoding"); if (_Py_INIT_FAILED(err)) { @@ -1431,7 +1447,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, } if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) { - err = CONFIG_DECODE_LOCALE(&config->stdio_errors, + err = CONFIG_DECODE_LOCALE(config, &config->stdio_errors, _Py_StandardStreamErrors, "_Py_StandardStreamErrors"); if (_Py_INIT_FAILED(err)) { @@ -1463,7 +1479,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* Does PYTHONIOENCODING contain an encoding? */ if (pythonioencoding[0]) { if (config->stdio_encoding == NULL) { - err = CONFIG_DECODE_LOCALE(&config->stdio_encoding, + err = CONFIG_DECODE_LOCALE(config, &config->stdio_encoding, pythonioencoding, "PYTHONIOENCODING environment variable"); if (_Py_INIT_FAILED(err)) { @@ -1482,7 +1498,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, } if (config->stdio_errors == NULL && errors != NULL) { - err = CONFIG_DECODE_LOCALE(&config->stdio_errors, + err = CONFIG_DECODE_LOCALE(config, &config->stdio_errors, errors, "PYTHONIOENCODING environment variable"); if (_Py_INIT_FAILED(err)) { @@ -1497,13 +1513,13 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* UTF-8 Mode uses UTF-8/surrogateescape */ if (preconfig->utf8_mode) { if (config->stdio_encoding == NULL) { - err = _PyCoreConfig_SetString(&config->stdio_encoding, L"utf-8"); + err = _PyCoreConfig_SetString(config, &config->stdio_encoding, L"utf-8"); if (_Py_INIT_FAILED(err)) { return err; } } if (config->stdio_errors == NULL) { - err = _PyCoreConfig_SetString(&config->stdio_errors, + err = _PyCoreConfig_SetString(config, &config->stdio_errors, L"surrogateescape"); if (_Py_INIT_FAILED(err)) { return err; @@ -1513,7 +1529,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* Choose the default error handler based on the current locale. */ if (config->stdio_encoding == NULL) { - err = config_get_locale_encoding(&config->stdio_encoding); + err = config_get_locale_encoding(config, &config->stdio_encoding); if (_Py_INIT_FAILED(err)) { return err; } @@ -1522,7 +1538,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, const wchar_t *errors = config_get_stdio_errors(config); assert(errors != NULL); - err = _PyCoreConfig_SetString(&config->stdio_errors, errors); + err = _PyCoreConfig_SetString(config, &config->stdio_errors, errors); if (_Py_INIT_FAILED(err)) { return err; } @@ -1539,34 +1555,35 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) if (config->filesystem_encoding == NULL) { #ifdef _Py_FORCE_UTF8_FS_ENCODING - err = _PyCoreConfig_SetString(&config->filesystem_encoding, L"utf-8"); + err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); #else #ifdef MS_WINDOWS if (preconfig->legacy_windows_fs_encoding) { /* Legacy Windows filesystem encoding: mbcs/replace */ - err = _PyCoreConfig_SetString(&config->filesystem_encoding, + err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"mbcs"); } else #endif if (preconfig->utf8_mode) { - err = _PyCoreConfig_SetString(&config->filesystem_encoding, + err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); } #ifndef MS_WINDOWS else if (_Py_GetForceASCII()) { - err = _PyCoreConfig_SetString(&config->filesystem_encoding, + err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"ascii"); } #endif else { #ifdef MS_WINDOWS /* Windows defaults to utf-8/surrogatepass (PEP 529). */ - err = _PyCoreConfig_SetString(&config->filesystem_encoding, + err = _PyCoreConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); #else - err = config_get_locale_encoding(&config->filesystem_encoding); + err = config_get_locale_encoding(config, + &config->filesystem_encoding); #endif } #endif /* !_Py_FORCE_UTF8_FS_ENCODING */ @@ -1588,7 +1605,7 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) #else errors = L"surrogateescape"; #endif - err = _PyCoreConfig_SetString(&config->filesystem_errors, errors); + err = _PyCoreConfig_SetString(config, &config->filesystem_errors, errors); if (_Py_INIT_FAILED(err)) { return err; } @@ -1681,7 +1698,7 @@ config_read(_PyCoreConfig *config) } if (config->check_hash_pycs_mode == NULL) { - err = _PyCoreConfig_SetString(&config->check_hash_pycs_mode, + err = _PyCoreConfig_SetString(config, &config->check_hash_pycs_mode, L"default"); if (_Py_INIT_FAILED(err)) { return err; @@ -1832,7 +1849,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions, || wcscmp(_PyOS_optarg, L"never") == 0 || wcscmp(_PyOS_optarg, L"default") == 0) { - err = _PyCoreConfig_SetString(&config->check_hash_pycs_mode, + err = _PyCoreConfig_SetString(config, &config->check_hash_pycs_mode, _PyOS_optarg); if (_Py_INIT_FAILED(err)) { return err; @@ -1966,7 +1983,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions, /* Get warning options from PYTHONWARNINGS environment variable. */ static _PyInitError -config_init_env_warnoptions(const _PyCoreConfig *config, _PyWstrList *warnoptions) +config_init_env_warnoptions(_PyCoreConfig *config, _PyWstrList *warnoptions) { _PyInitError err; /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */ @@ -2136,8 +2153,7 @@ core_read_precmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) } _PyPreConfig preconfig; - _PyPreConfig_Init(&preconfig); - _PyPreConfig_Copy(&preconfig, &_PyRuntime.preconfig); + _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig); _PyPreConfig_GetCoreConfig(&preconfig, config); @@ -2211,24 +2227,11 @@ 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; - } - } + _PyInitError err = _Py_PreInitializeFromCoreConfig(config, args); + if (_Py_INIT_FAILED(err)) { + return err; } + return _PyArgv_AsWstrList(args, &config->argv); } @@ -2236,7 +2239,7 @@ _PyCoreConfig_SetPyArgv(_PyCoreConfig *config, const _PyArgv *args) /* 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, Py_ssize_t argc, char **argv) +_PyCoreConfig_SetArgv(_PyCoreConfig *config, Py_ssize_t argc, char * const *argv) { _PyArgv args = { .argc = argc, @@ -2248,7 +2251,7 @@ _PyCoreConfig_SetArgv(_PyCoreConfig *config, Py_ssize_t argc, char **argv) _PyInitError -_PyCoreConfig_SetWideArgv(_PyCoreConfig *config, Py_ssize_t argc, wchar_t **argv) +_PyCoreConfig_SetWideArgv(_PyCoreConfig *config, Py_ssize_t argc, wchar_t * const *argv) { _PyArgv args = { .argc = argc, diff --git a/Python/preconfig.c b/Python/preconfig.c index 0f4bd8e..71a6ee6 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -95,7 +95,7 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list) } else { wargv.length = args->argc; - wargv.items = args->wchar_argv; + wargv.items = (wchar_t **)args->wchar_argv; if (_PyWstrList_Copy(list, &wargv) < 0) { return _Py_INIT_NO_MEMORY(); } @@ -217,16 +217,15 @@ precmdline_parse_cmdline(_PyPreCmdline *cmdline) _PyInitError -_PyPreCmdline_Read(_PyPreCmdline *cmdline, - const _PyPreConfig *preconfig) +_PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig) { - if (preconfig) { - _PyPreCmdline_GetPreConfig(cmdline, preconfig); - } + _PyPreCmdline_GetPreConfig(cmdline, preconfig); - _PyInitError err = precmdline_parse_cmdline(cmdline); - if (_Py_INIT_FAILED(err)) { - return err; + if (preconfig->parse_argv) { + _PyInitError err = precmdline_parse_cmdline(cmdline); + if (_Py_INIT_FAILED(err)) { + return err; + } } /* isolated, use_environment */ @@ -268,6 +267,7 @@ _PyPreConfig_Init(_PyPreConfig *config) memset(config, 0, sizeof(*config)); config->_config_version = _Py_CONFIG_VERSION; + config->parse_argv = 0; config->isolated = -1; config->use_environment = -1; config->configure_locale = 1; @@ -285,6 +285,7 @@ _PyPreConfig_InitPythonConfig(_PyPreConfig *config) { _PyPreConfig_Init(config); + config->parse_argv = 1; /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540) depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE environment variables. */ @@ -311,10 +312,40 @@ _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config) void +_PyPreConfig_InitFromPreConfig(_PyPreConfig *config, + const _PyPreConfig *config2) +{ + _PyPreConfig_Init(config); + _PyPreConfig_Copy(config, config2); +} + + +void +_PyPreConfig_InitFromCoreConfig(_PyPreConfig *config, + const _PyCoreConfig *coreconfig) +{ + _PyCoreConfigInitEnum config_init = (_PyCoreConfigInitEnum)coreconfig->_config_init; + switch (config_init) { + case _PyCoreConfig_INIT_PYTHON: + _PyPreConfig_InitPythonConfig(config); + break; + case _PyCoreConfig_INIT_ISOLATED: + _PyPreConfig_InitIsolatedConfig(config); + break; + case _PyCoreConfig_INIT: + default: + _PyPreConfig_Init(config); + } + _PyPreConfig_GetCoreConfig(config, coreconfig); +} + + +void _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) { #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR + COPY_ATTR(parse_argv); COPY_ATTR(isolated); COPY_ATTR(use_environment); COPY_ATTR(configure_locale); @@ -341,27 +372,20 @@ _PyPreConfig_AsDict(const _PyPreConfig *config) return NULL; } -#define SET_ITEM(KEY, EXPR) \ +#define SET_ITEM_INT(ATTR) \ do { \ - PyObject *obj = (EXPR); \ + PyObject *obj = PyLong_FromLong(config->ATTR); \ if (obj == NULL) { \ goto fail; \ } \ - int res = PyDict_SetItemString(dict, (KEY), obj); \ + int res = PyDict_SetItemString(dict, #ATTR, obj); \ Py_DECREF(obj); \ if (res < 0) { \ goto fail; \ } \ } while (0) -#define SET_ITEM_INT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) -#define FROM_STRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromString(STR) \ - : (Py_INCREF(Py_None), Py_None)) -#define SET_ITEM_STR(ATTR) \ - SET_ITEM(#ATTR, FROM_STRING(config->ATTR)) + SET_ITEM_INT(parse_argv); SET_ITEM_INT(isolated); SET_ITEM_INT(use_environment); SET_ITEM_INT(configure_locale); @@ -379,10 +403,7 @@ fail: Py_DECREF(dict); return NULL; -#undef FROM_STRING -#undef SET_ITEM #undef SET_ITEM_INT -#undef SET_ITEM_STR } @@ -395,6 +416,7 @@ _PyPreConfig_GetCoreConfig(_PyPreConfig *config, config->ATTR = core_config->ATTR; \ } + COPY_ATTR(parse_argv); COPY_ATTR(isolated); COPY_ATTR(use_environment); COPY_ATTR(dev_mode); @@ -662,9 +684,11 @@ preconfig_init_allocator(_PyPreConfig *config) allocators to "malloc" (and not to "debug"). */ const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC"); if (envvar) { - if (_PyMem_GetAllocatorName(envvar, &config->allocator) < 0) { + PyMemAllocatorName name; + if (_PyMem_GetAllocatorName(envvar, &name) < 0) { return _Py_INIT_ERR("PYTHONMALLOC: unknown allocator"); } + config->allocator = (int)name; } } @@ -751,8 +775,7 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) /* Save the config to be able to restore it if encodings change */ _PyPreConfig save_config; - _PyPreConfig_Init(&save_config); - _PyPreConfig_Copy(&save_config, config); + _PyPreConfig_InitFromPreConfig(&save_config, config); /* Set LC_CTYPE to the user preferred locale */ if (config->configure_locale) { @@ -879,8 +902,9 @@ _PyPreConfig_Write(const _PyPreConfig *config) return _Py_INIT_OK(); } - if (config->allocator != PYMEM_ALLOCATOR_NOT_SET) { - if (_PyMem_SetupAllocators(config->allocator) < 0) { + PyMemAllocatorName name = (PyMemAllocatorName)config->allocator; + if (name != PYMEM_ALLOCATOR_NOT_SET) { + if (_PyMem_SetupAllocators(name) < 0) { return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator"); } } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0781dc8..01f725f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -691,6 +691,10 @@ _Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) { _PyInitError err; + if (src_config == NULL) { + return _Py_INIT_ERR("preinitialization config is NULL"); + } + err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(err)) { return err; @@ -703,11 +707,7 @@ _Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) } _PyPreConfig config; - _PyPreConfig_Init(&config); - - if (src_config) { - _PyPreConfig_Copy(&config, src_config); - } + _PyPreConfig_InitFromPreConfig(&config, src_config); err = _PyPreConfig_Read(&config, args); if (_Py_INIT_FAILED(err)) { @@ -751,21 +751,34 @@ _PyInitError _Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, const _PyArgv *args) { - _PyPreConfig config; - _PyPreConfig_Init(&config); - if (coreconfig != NULL) { - _PyPreConfig_GetCoreConfig(&config, coreconfig); + assert(coreconfig != NULL); + + _PyInitError err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + if (runtime->pre_initialized) { + /* Already initialized: do nothing */ + return _Py_INIT_OK(); } - if (args == NULL && coreconfig != NULL && coreconfig->parse_argv) { + _PyPreConfig preconfig; + _PyPreConfig_InitFromCoreConfig(&preconfig, coreconfig); + + if (!coreconfig->parse_argv) { + return _Py_PreInitialize(&preconfig); + } + else if (args == NULL) { _PyArgv config_args = { .use_bytes_argv = 0, .argc = coreconfig->argv.length, .wchar_argv = coreconfig->argv.items}; - return _Py_PreInitializeFromPyArgv(&config, &config_args); + return _Py_PreInitializeFromPyArgv(&preconfig, &config_args); } else { - return _Py_PreInitializeFromPyArgv(&config, args); + return _Py_PreInitializeFromPyArgv(&preconfig, args); } } @@ -777,13 +790,11 @@ pyinit_coreconfig(_PyRuntimeState *runtime, const _PyArgv *args, PyInterpreterState **interp_p) { - _PyInitError err; + assert(src_config != NULL); - if (src_config) { - err = _PyCoreConfig_Copy(config, src_config); - if (_Py_INIT_FAILED(err)) { - return err; - } + _PyInitError err = _PyCoreConfig_Copy(config, src_config); + if (_Py_INIT_FAILED(err)) { + return err; } if (args) { @@ -995,6 +1006,10 @@ _Py_InitializeMain(void) static _PyInitError init_python(const _PyCoreConfig *config, const _PyArgv *args) { + if (config == NULL) { + return _Py_INIT_ERR("initialization config is NULL"); + } + _PyInitError err; err = _PyRuntime_Initialize(); @@ -1022,7 +1037,8 @@ init_python(const _PyCoreConfig *config, const _PyArgv *args) _PyInitError -_Py_InitializeFromArgs(const _PyCoreConfig *config, Py_ssize_t argc, char **argv) +_Py_InitializeFromArgs(const _PyCoreConfig *config, + Py_ssize_t argc, char * const *argv) { _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv}; return init_python(config, &args); @@ -1030,7 +1046,8 @@ _Py_InitializeFromArgs(const _PyCoreConfig *config, Py_ssize_t argc, char **argv _PyInitError -_Py_InitializeFromWideArgs(const _PyCoreConfig *config, Py_ssize_t argc, wchar_t **argv) +_Py_InitializeFromWideArgs(const _PyCoreConfig *config, + Py_ssize_t argc, wchar_t * const *argv) { _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv}; return init_python(config, &args); |