mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-32030: Fix usage of memory allocators (#4953)
* _Py_InitializeCore() doesn't call _PyMem_SetupAllocators() anymore if the PYTHONMALLOC environment variable is not set. * pymain_cmdline() now sets the allocator to the default, instead of setting the allocator in subfunctions. * Py_SetStandardStreamEncoding() now calls _PyMem_SetDefaultAllocator() to get a known allocator, to be able to release the memory with the same allocator.
This commit is contained in:
parent
83cb778b4a
commit
31e99080f6
3 changed files with 50 additions and 12 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
Py_Initialize() doesn't reset the memory allocators to default if the
|
||||||
|
``PYTHONMALLOC`` environment variable is not set.
|
|
@ -649,11 +649,12 @@ pymain_free_raw(_PyMain *pymain)
|
||||||
Py_Initialize()-Py_Finalize() can be called multiple times. */
|
Py_Initialize()-Py_Finalize() can be called multiple times. */
|
||||||
_PyPathConfig_Clear(&_Py_path_config);
|
_PyPathConfig_Clear(&_Py_path_config);
|
||||||
|
|
||||||
|
pymain_clear_config(pymain);
|
||||||
|
|
||||||
/* Force the allocator used by pymain_read_conf() */
|
/* Force the allocator used by pymain_read_conf() */
|
||||||
PyMemAllocatorEx old_alloc;
|
PyMemAllocatorEx old_alloc;
|
||||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
_PyCoreConfig_Clear(&pymain->config);
|
|
||||||
pymain_clear_pymain(pymain);
|
pymain_clear_pymain(pymain);
|
||||||
|
|
||||||
clear_wstrlist(orig_argc, orig_argv);
|
clear_wstrlist(orig_argc, orig_argv);
|
||||||
|
@ -1963,11 +1964,6 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline)
|
||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
/* Force default allocator, since pymain_free() must use the same allocator
|
|
||||||
than this function. */
|
|
||||||
PyMemAllocatorEx old_alloc;
|
|
||||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
||||||
|
|
||||||
char *oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
|
char *oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
|
||||||
if (oldloc == NULL) {
|
if (oldloc == NULL) {
|
||||||
pymain->err = _Py_INIT_NO_MEMORY();
|
pymain->err = _Py_INIT_NO_MEMORY();
|
||||||
|
@ -2055,7 +2051,6 @@ done:
|
||||||
PyMem_RawFree(oldloc);
|
PyMem_RawFree(oldloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2578,6 +2573,15 @@ pymain_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline)
|
||||||
static int
|
static int
|
||||||
pymain_cmdline(_PyMain *pymain)
|
pymain_cmdline(_PyMain *pymain)
|
||||||
{
|
{
|
||||||
|
/* Force default allocator, since pymain_free() and pymain_clear_config()
|
||||||
|
must use the same allocator than this function. */
|
||||||
|
PyMemAllocatorEx old_alloc;
|
||||||
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
PyMemAllocatorEx default_alloc;
|
||||||
|
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &default_alloc);
|
||||||
|
#endif
|
||||||
|
|
||||||
_Py_CommandLineDetails cmdline;
|
_Py_CommandLineDetails cmdline;
|
||||||
memset(&cmdline, 0, sizeof(cmdline));
|
memset(&cmdline, 0, sizeof(cmdline));
|
||||||
|
|
||||||
|
@ -2588,6 +2592,14 @@ pymain_cmdline(_PyMain *pymain)
|
||||||
pymain_set_global_config(pymain, &cmdline);
|
pymain_set_global_config(pymain, &cmdline);
|
||||||
|
|
||||||
pymain_clear_cmdline(pymain, &cmdline);
|
pymain_clear_cmdline(pymain, &cmdline);
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* Make sure that PYMEM_DOMAIN_RAW has not been modified */
|
||||||
|
PyMemAllocatorEx cur_alloc;
|
||||||
|
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &cur_alloc);
|
||||||
|
assert(memcmp(&cur_alloc, &default_alloc, sizeof(cur_alloc)) == 0);
|
||||||
|
#endif
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,15 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||||
/* This is too late to have any effect */
|
/* This is too late to have any effect */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
/* Py_SetStandardStreamEncoding() can be called before Py_Initialize(),
|
||||||
|
but Py_Initialize() can change the allocator. Use a known allocator
|
||||||
|
to be able to release the memory later. */
|
||||||
|
PyMemAllocatorEx old_alloc;
|
||||||
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
/* Can't call PyErr_NoMemory() on errors, as Python hasn't been
|
/* Can't call PyErr_NoMemory() on errors, as Python hasn't been
|
||||||
* initialised yet.
|
* initialised yet.
|
||||||
*
|
*
|
||||||
|
@ -182,7 +191,8 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||||
if (encoding) {
|
if (encoding) {
|
||||||
_Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
|
_Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
|
||||||
if (!_Py_StandardStreamEncoding) {
|
if (!_Py_StandardStreamEncoding) {
|
||||||
return -2;
|
res = -2;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (errors) {
|
if (errors) {
|
||||||
|
@ -191,7 +201,8 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||||
if (_Py_StandardStreamEncoding) {
|
if (_Py_StandardStreamEncoding) {
|
||||||
PyMem_RawFree(_Py_StandardStreamEncoding);
|
PyMem_RawFree(_Py_StandardStreamEncoding);
|
||||||
}
|
}
|
||||||
return -3;
|
res = -3;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -200,7 +211,11 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
|
||||||
Py_LegacyWindowsStdioFlag = 1;
|
Py_LegacyWindowsStdioFlag = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
|
||||||
|
done:
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -597,8 +612,10 @@ _Py_InitializeCore(const _PyCoreConfig *core_config)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyMem_SetupAllocators(core_config->allocator) < 0) {
|
if (core_config->allocator != NULL) {
|
||||||
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
|
if (_PyMem_SetupAllocators(core_config->allocator) < 0) {
|
||||||
|
return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyRuntime.initialized) {
|
if (_PyRuntime.initialized) {
|
||||||
|
@ -1818,7 +1835,11 @@ init_sys_streams(PyInterpreterState *interp)
|
||||||
error:
|
error:
|
||||||
res = _Py_INIT_ERR("can't initialize sys standard streams");
|
res = _Py_INIT_ERR("can't initialize sys standard streams");
|
||||||
|
|
||||||
|
/* Use the same allocator than Py_SetStandardStreamEncoding() */
|
||||||
|
PyMemAllocatorEx old_alloc;
|
||||||
done:
|
done:
|
||||||
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
/* We won't need them anymore. */
|
/* We won't need them anymore. */
|
||||||
if (_Py_StandardStreamEncoding) {
|
if (_Py_StandardStreamEncoding) {
|
||||||
PyMem_RawFree(_Py_StandardStreamEncoding);
|
PyMem_RawFree(_Py_StandardStreamEncoding);
|
||||||
|
@ -1828,6 +1849,9 @@ done:
|
||||||
PyMem_RawFree(_Py_StandardStreamErrors);
|
PyMem_RawFree(_Py_StandardStreamErrors);
|
||||||
_Py_StandardStreamErrors = NULL;
|
_Py_StandardStreamErrors = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
PyMem_Free(pythonioencoding);
|
PyMem_Free(pythonioencoding);
|
||||||
Py_XDECREF(bimod);
|
Py_XDECREF(bimod);
|
||||||
Py_XDECREF(iomod);
|
Py_XDECREF(iomod);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue