bpo-36142: _PyPreConfig_Write() sets the allocator (GH-12186)

* _PyPreConfig_Write() now sets the memory allocator.
* _PyPreConfig_Write() gets a return type: _PyInitError.
* _Py_InitializeCore() now reads and writes the pre-configuration
  (set the memory allocator, configure the locale) before reading and
  writing the core configuration.
This commit is contained in:
Victor Stinner 2019-03-06 00:36:56 +01:00 committed by GitHub
parent a9df651eb4
commit 7d2ef3ef50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 43 deletions

View File

@ -59,7 +59,7 @@ PyAPI_FUNC(int) _PyPreConfig_AsDict(const _PyPreConfig *config,
PyObject *dict);
PyAPI_FUNC(_PyInitError) _PyPreConfig_ReadFromArgv(_PyPreConfig *config,
const _PyArgv *args);
PyAPI_FUNC(void) _PyPreConfig_Write(const _PyPreConfig *config);
PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config);
/* --- _PyCoreConfig ---------------------------------------------- */

View File

@ -304,8 +304,7 @@ preconfig_read_write(_PyPreConfig *config, const _PyArgv *args)
return err;
}
_PyPreConfig_Write(config);
return _Py_INIT_OK();
return _PyPreConfig_Write(config);
}

View File

@ -741,9 +741,35 @@ done:
}
void
static _PyInitError
_PyPreConfig_Reconfigure(const _PyPreConfig *config)
{
if (config->allocator != NULL) {
const char *allocator = _PyMem_GetAllocatorsName();
if (allocator == NULL || strcmp(config->allocator, allocator) != 0) {
return _Py_INIT_USER_ERR("cannot modify memory allocator "
"after first Py_Initialize()");
}
}
return _Py_INIT_OK();
}
_PyInitError
_PyPreConfig_Write(const _PyPreConfig *config)
{
if (_PyRuntime.core_initialized) {
/* bpo-34008: Calling Py_Main() after Py_Initialize() ignores
the new configuration. */
return _PyPreConfig_Reconfigure(config);
}
if (config->allocator != NULL) {
if (_PyMem_SetupAllocators(config->allocator) < 0) {
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
}
}
_PyPreConfig_SetGlobalConfig(config);
if (config->coerce_c_locale) {
@ -752,4 +778,6 @@ _PyPreConfig_Write(const _PyPreConfig *config)
/* Set LC_CTYPE to the user preferred locale */
_Py_SetLocaleFromEnv(LC_CTYPE);
return _Py_INIT_OK();
}

View File

@ -480,16 +480,6 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p,
}
*interp_p = interp;
/* bpo-34008: For backward compatibility reasons, calling Py_Main() after
Py_Initialize() ignores the new configuration. */
if (core_config->preconfig.allocator != NULL) {
const char *allocator = _PyMem_GetAllocatorsName();
if (allocator == NULL || strcmp(core_config->preconfig.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) {
@ -521,12 +511,6 @@ pycore_init_runtime(const _PyCoreConfig *core_config)
return err;
}
if (core_config->preconfig.allocator != NULL) {
if (_PyMem_SetupAllocators(core_config->preconfig.allocator) < 0) {
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
}
}
/* Py_Finalize leaves _Py_Finalizing set in order to help daemon
* threads behave a little more gracefully at interpreter shutdown.
* We clobber it here so the new interpreter can start with a clean
@ -728,6 +712,65 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
return _Py_INIT_OK();
}
static _PyInitError
pyinit_preconfig(_PyPreConfig *preconfig, const _PyPreConfig *src_preconfig)
{
_PyInitError err;
PyMemAllocatorEx old_alloc;
/* Set LC_CTYPE to the user preferred locale */
_Py_SetLocaleFromEnv(LC_CTYPE);
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_PyPreConfig_Copy(preconfig, src_preconfig) >= 0) {
err = _PyPreConfig_Read(preconfig);
}
else {
err = _Py_INIT_ERR("failed to copy pre config");
}
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_INIT_FAILED(err)) {
return err;
}
return _PyPreConfig_Write(preconfig);
}
static _PyInitError
pyinit_coreconfig(_PyCoreConfig *config, const _PyCoreConfig *src_config,
PyInterpreterState **interp_p)
{
PyMemAllocatorEx old_alloc;
_PyInitError err;
/* Set LC_CTYPE to the user preferred locale */
_Py_SetLocaleFromEnv(LC_CTYPE);
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_PyCoreConfig_Copy(config, src_config) >= 0) {
err = _PyCoreConfig_Read(config, NULL);
}
else {
err = _Py_INIT_ERR("failed to copy core config");
}
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_INIT_FAILED(err)) {
return err;
}
if (!_PyRuntime.core_initialized) {
return _Py_InitializeCore_impl(interp_p, config);
}
else {
return _Py_Initialize_ReconfigureCore(interp_p, config);
}
}
/* Begin interpreter initialization
*
* On return, the first thread and interpreter state have been created,
@ -749,41 +792,23 @@ _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;
assert(src_config != NULL);
/* Set LC_CTYPE to the user preferred locale */
_Py_SetLocaleFromEnv(LC_CTYPE);
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_PyCoreConfig_Copy(&config, src_config) >= 0) {
err = _PyCoreConfig_Read(&config, NULL);
}
else {
err = _Py_INIT_ERR("failed to copy core config");
}
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
_PyCoreConfig local_config = _PyCoreConfig_INIT;
err = pyinit_preconfig(&local_config.preconfig, &src_config->preconfig);
if (_Py_INIT_FAILED(err)) {
goto done;
}
if (!_PyRuntime.core_initialized) {
err = _Py_InitializeCore_impl(interp_p, &config);
}
else {
err = _Py_Initialize_ReconfigureCore(interp_p, &config);
}
err = pyinit_coreconfig(&local_config, src_config, interp_p);
done:
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
_PyCoreConfig_Clear(&config);
_PyCoreConfig_Clear(&local_config);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return err;