summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-20 09:02:00 (GMT)
committerGitHub <noreply@github.com>2019-05-20 09:02:00 (GMT)
commit6d1c46746e17367caf8a24623cb5c9a9c4e3e036 (patch)
tree17ea108a38c01e32ec2d3a25df03bd47968af7ff /Python
parent6d965b39b7a486dd9e96a60b19ee92382d668299 (diff)
downloadcpython-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.c123
-rw-r--r--Python/preconfig.c80
-rw-r--r--Python/pylifecycle.c57
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);