Skip to content

Commit 7d2ef3e

Browse files
authored
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.
1 parent a9df651 commit 7d2ef3e

File tree

4 files changed

+95
-43
lines changed

4 files changed

+95
-43
lines changed

Include/internal/pycore_coreconfig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ PyAPI_FUNC(int) _PyPreConfig_AsDict(const _PyPreConfig *config,
5959
PyObject *dict);
6060
PyAPI_FUNC(_PyInitError) _PyPreConfig_ReadFromArgv(_PyPreConfig *config,
6161
const _PyArgv *args);
62-
PyAPI_FUNC(void) _PyPreConfig_Write(const _PyPreConfig *config);
62+
PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config);
6363

6464

6565
/* --- _PyCoreConfig ---------------------------------------------- */

Modules/main.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ preconfig_read_write(_PyPreConfig *config, const _PyArgv *args)
304304
return err;
305305
}
306306

307-
_PyPreConfig_Write(config);
308-
return _Py_INIT_OK();
307+
return _PyPreConfig_Write(config);
309308
}
310309

311310

Python/preconfig.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,35 @@ _PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
741741
}
742742

743743

744-
void
744+
static _PyInitError
745+
_PyPreConfig_Reconfigure(const _PyPreConfig *config)
746+
{
747+
if (config->allocator != NULL) {
748+
const char *allocator = _PyMem_GetAllocatorsName();
749+
if (allocator == NULL || strcmp(config->allocator, allocator) != 0) {
750+
return _Py_INIT_USER_ERR("cannot modify memory allocator "
751+
"after first Py_Initialize()");
752+
}
753+
}
754+
return _Py_INIT_OK();
755+
}
756+
757+
758+
_PyInitError
745759
_PyPreConfig_Write(const _PyPreConfig *config)
746760
{
761+
if (_PyRuntime.core_initialized) {
762+
/* bpo-34008: Calling Py_Main() after Py_Initialize() ignores
763+
the new configuration. */
764+
return _PyPreConfig_Reconfigure(config);
765+
}
766+
767+
if (config->allocator != NULL) {
768+
if (_PyMem_SetupAllocators(config->allocator) < 0) {
769+
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
770+
}
771+
}
772+
747773
_PyPreConfig_SetGlobalConfig(config);
748774

749775
if (config->coerce_c_locale) {
@@ -752,4 +778,6 @@ _PyPreConfig_Write(const _PyPreConfig *config)
752778

753779
/* Set LC_CTYPE to the user preferred locale */
754780
_Py_SetLocaleFromEnv(LC_CTYPE);
781+
782+
return _Py_INIT_OK();
755783
}

Python/pylifecycle.c

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -480,16 +480,6 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p,
480480
}
481481
*interp_p = interp;
482482

483-
/* bpo-34008: For backward compatibility reasons, calling Py_Main() after
484-
Py_Initialize() ignores the new configuration. */
485-
if (core_config->preconfig.allocator != NULL) {
486-
const char *allocator = _PyMem_GetAllocatorsName();
487-
if (allocator == NULL || strcmp(core_config->preconfig.allocator, allocator) != 0) {
488-
return _Py_INIT_USER_ERR("cannot modify memory allocator "
489-
"after first Py_Initialize()");
490-
}
491-
}
492-
493483
_PyCoreConfig_SetGlobalConfig(core_config);
494484

495485
if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) {
@@ -521,12 +511,6 @@ pycore_init_runtime(const _PyCoreConfig *core_config)
521511
return err;
522512
}
523513

524-
if (core_config->preconfig.allocator != NULL) {
525-
if (_PyMem_SetupAllocators(core_config->preconfig.allocator) < 0) {
526-
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
527-
}
528-
}
529-
530514
/* Py_Finalize leaves _Py_Finalizing set in order to help daemon
531515
* threads behave a little more gracefully at interpreter shutdown.
532516
* We clobber it here so the new interpreter can start with a clean
@@ -728,6 +712,65 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
728712
return _Py_INIT_OK();
729713
}
730714

715+
716+
static _PyInitError
717+
pyinit_preconfig(_PyPreConfig *preconfig, const _PyPreConfig *src_preconfig)
718+
{
719+
_PyInitError err;
720+
PyMemAllocatorEx old_alloc;
721+
722+
/* Set LC_CTYPE to the user preferred locale */
723+
_Py_SetLocaleFromEnv(LC_CTYPE);
724+
725+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
726+
if (_PyPreConfig_Copy(preconfig, src_preconfig) >= 0) {
727+
err = _PyPreConfig_Read(preconfig);
728+
}
729+
else {
730+
err = _Py_INIT_ERR("failed to copy pre config");
731+
}
732+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
733+
734+
if (_Py_INIT_FAILED(err)) {
735+
return err;
736+
}
737+
738+
return _PyPreConfig_Write(preconfig);
739+
}
740+
741+
742+
static _PyInitError
743+
pyinit_coreconfig(_PyCoreConfig *config, const _PyCoreConfig *src_config,
744+
PyInterpreterState **interp_p)
745+
{
746+
PyMemAllocatorEx old_alloc;
747+
_PyInitError err;
748+
749+
/* Set LC_CTYPE to the user preferred locale */
750+
_Py_SetLocaleFromEnv(LC_CTYPE);
751+
752+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
753+
if (_PyCoreConfig_Copy(config, src_config) >= 0) {
754+
err = _PyCoreConfig_Read(config, NULL);
755+
}
756+
else {
757+
err = _Py_INIT_ERR("failed to copy core config");
758+
}
759+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
760+
761+
if (_Py_INIT_FAILED(err)) {
762+
return err;
763+
}
764+
765+
if (!_PyRuntime.core_initialized) {
766+
return _Py_InitializeCore_impl(interp_p, config);
767+
}
768+
else {
769+
return _Py_Initialize_ReconfigureCore(interp_p, config);
770+
}
771+
}
772+
773+
731774
/* Begin interpreter initialization
732775
*
733776
* On return, the first thread and interpreter state have been created,
@@ -749,41 +792,23 @@ _PyInitError
749792
_Py_InitializeCore(PyInterpreterState **interp_p,
750793
const _PyCoreConfig *src_config)
751794
{
752-
assert(src_config != NULL);
753-
754795
PyMemAllocatorEx old_alloc;
755796
_PyInitError err;
756797

757-
/* Copy the configuration, since _PyCoreConfig_Read() modifies it
758-
(and the input configuration is read only). */
759-
_PyCoreConfig config = _PyCoreConfig_INIT;
760-
761-
/* Set LC_CTYPE to the user preferred locale */
762-
_Py_SetLocaleFromEnv(LC_CTYPE);
798+
assert(src_config != NULL);
763799

764-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
765-
if (_PyCoreConfig_Copy(&config, src_config) >= 0) {
766-
err = _PyCoreConfig_Read(&config, NULL);
767-
}
768-
else {
769-
err = _Py_INIT_ERR("failed to copy core config");
770-
}
771-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
800+
_PyCoreConfig local_config = _PyCoreConfig_INIT;
772801

802+
err = pyinit_preconfig(&local_config.preconfig, &src_config->preconfig);
773803
if (_Py_INIT_FAILED(err)) {
774804
goto done;
775805
}
776806

777-
if (!_PyRuntime.core_initialized) {
778-
err = _Py_InitializeCore_impl(interp_p, &config);
779-
}
780-
else {
781-
err = _Py_Initialize_ReconfigureCore(interp_p, &config);
782-
}
807+
err = pyinit_coreconfig(&local_config, src_config, interp_p);
783808

784809
done:
785810
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
786-
_PyCoreConfig_Clear(&config);
811+
_PyCoreConfig_Clear(&local_config);
787812
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
788813

789814
return err;

0 commit comments

Comments
 (0)