Commit 31e99080 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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.
parent 83cb778b
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) ...@@ -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) ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment