mirror of
https://github.com/python/cpython.git
synced 2025-08-23 18:24:46 +00:00
gh-111924: Fix data races when swapping allocators (gh-130287)
CPython current temporarily changes `PYMEM_DOMAIN_RAW` to the default allocator during initialization and shutdown. The motivation is to ensure that core runtime structures are allocated and freed using the same allocator. However, modifying the current allocator changes global state and is not thread-safe even with the GIL. Other threads may be allocating or freeing objects use PYMEM_DOMAIN_RAW; they are not required to hold the GIL to call PyMem_RawMalloc/PyMem_RawFree. This adds new internal-only functions like `_PyMem_DefaultRawMalloc` that aren't affected by calls to `PyMem_SetAllocator()`, so they're appropriate for Python runtime initialization and finalization. Use these calls in places where we previously swapped to the default raw allocator.
This commit is contained in:
parent
568db400ff
commit
ca22147547
9 changed files with 155 additions and 154 deletions
|
@ -4,7 +4,7 @@
|
|||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||
#include "pycore_fileutils.h" // _Py_wgetcwd()
|
||||
#include "pycore_pathconfig.h"
|
||||
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
|
||||
#include "pycore_pymem.h" // _PyMem_DefaultRawFree()
|
||||
#include <wchar.h>
|
||||
|
||||
#include "marshal.h" // PyMarshal_ReadObjectFromString
|
||||
|
@ -54,12 +54,9 @@ _PyPathConfig_GetGlobalModuleSearchPath(void)
|
|||
void
|
||||
_PyPathConfig_ClearGlobal(void)
|
||||
{
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
#define CLEAR(ATTR) \
|
||||
do { \
|
||||
PyMem_RawFree(_Py_path_config.ATTR); \
|
||||
_PyMem_DefaultRawFree(_Py_path_config.ATTR); \
|
||||
_Py_path_config.ATTR = NULL; \
|
||||
} while (0)
|
||||
|
||||
|
@ -74,8 +71,6 @@ _PyPathConfig_ClearGlobal(void)
|
|||
_Py_path_config._is_python_build = 0;
|
||||
|
||||
#undef CLEAR
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
}
|
||||
|
||||
PyStatus
|
||||
|
@ -126,14 +121,11 @@ done:
|
|||
PyStatus
|
||||
_PyPathConfig_UpdateGlobal(const PyConfig *config)
|
||||
{
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
#define COPY(ATTR) \
|
||||
do { \
|
||||
if (config->ATTR) { \
|
||||
PyMem_RawFree(_Py_path_config.ATTR); \
|
||||
_Py_path_config.ATTR = _PyMem_RawWcsdup(config->ATTR); \
|
||||
_PyMem_DefaultRawFree(_Py_path_config.ATTR); \
|
||||
_Py_path_config.ATTR = _PyMem_DefaultRawWcsdup(config->ATTR); \
|
||||
if (!_Py_path_config.ATTR) goto error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -141,8 +133,8 @@ _PyPathConfig_UpdateGlobal(const PyConfig *config)
|
|||
#define COPY2(ATTR, SRCATTR) \
|
||||
do { \
|
||||
if (config->SRCATTR) { \
|
||||
PyMem_RawFree(_Py_path_config.ATTR); \
|
||||
_Py_path_config.ATTR = _PyMem_RawWcsdup(config->SRCATTR); \
|
||||
_PyMem_DefaultRawFree(_Py_path_config.ATTR); \
|
||||
_Py_path_config.ATTR = _PyMem_DefaultRawWcsdup(config->SRCATTR); \
|
||||
if (!_Py_path_config.ATTR) goto error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -165,9 +157,9 @@ _PyPathConfig_UpdateGlobal(const PyConfig *config)
|
|||
#undef COPY2
|
||||
#undef COPY_INT
|
||||
|
||||
PyMem_RawFree(_Py_path_config.module_search_path);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.module_search_path);
|
||||
_Py_path_config.module_search_path = NULL;
|
||||
PyMem_RawFree(_Py_path_config.calculated_module_search_path);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.calculated_module_search_path);
|
||||
_Py_path_config.calculated_module_search_path = NULL;
|
||||
|
||||
do {
|
||||
|
@ -176,7 +168,7 @@ _PyPathConfig_UpdateGlobal(const PyConfig *config)
|
|||
cch += 1 + wcslen(config->module_search_paths.items[i]);
|
||||
}
|
||||
|
||||
wchar_t *path = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t) * cch);
|
||||
wchar_t *path = (wchar_t*)_PyMem_DefaultRawMalloc(sizeof(wchar_t) * cch);
|
||||
if (!path) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -194,11 +186,9 @@ _PyPathConfig_UpdateGlobal(const PyConfig *config)
|
|||
_Py_path_config.calculated_module_search_path = path;
|
||||
} while (0);
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
return _PyStatus_OK();
|
||||
|
||||
error:
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
return _PyStatus_NO_MEMORY();
|
||||
}
|
||||
|
||||
|
@ -218,29 +208,24 @@ Py_SetPath(const wchar_t *path)
|
|||
return;
|
||||
}
|
||||
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.prefix);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.exec_prefix);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.stdlib_dir);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.module_search_path);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.calculated_module_search_path);
|
||||
|
||||
PyMem_RawFree(_Py_path_config.prefix);
|
||||
PyMem_RawFree(_Py_path_config.exec_prefix);
|
||||
PyMem_RawFree(_Py_path_config.stdlib_dir);
|
||||
PyMem_RawFree(_Py_path_config.module_search_path);
|
||||
PyMem_RawFree(_Py_path_config.calculated_module_search_path);
|
||||
|
||||
_Py_path_config.prefix = _PyMem_RawWcsdup(L"");
|
||||
_Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
|
||||
_Py_path_config.prefix = _PyMem_DefaultRawWcsdup(L"");
|
||||
_Py_path_config.exec_prefix = _PyMem_DefaultRawWcsdup(L"");
|
||||
// XXX Copy this from the new module_search_path?
|
||||
if (_Py_path_config.home != NULL) {
|
||||
_Py_path_config.stdlib_dir = _PyMem_RawWcsdup(_Py_path_config.home);
|
||||
_Py_path_config.stdlib_dir = _PyMem_DefaultRawWcsdup(_Py_path_config.home);
|
||||
}
|
||||
else {
|
||||
_Py_path_config.stdlib_dir = _PyMem_RawWcsdup(L"");
|
||||
_Py_path_config.stdlib_dir = _PyMem_DefaultRawWcsdup(L"");
|
||||
}
|
||||
_Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
|
||||
_Py_path_config.module_search_path = _PyMem_DefaultRawWcsdup(path);
|
||||
_Py_path_config.calculated_module_search_path = NULL;
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
if (_Py_path_config.prefix == NULL
|
||||
|| _Py_path_config.exec_prefix == NULL
|
||||
|| _Py_path_config.stdlib_dir == NULL
|
||||
|
@ -256,18 +241,13 @@ Py_SetPythonHome(const wchar_t *home)
|
|||
{
|
||||
int has_value = home && home[0];
|
||||
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
PyMem_RawFree(_Py_path_config.home);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.home);
|
||||
_Py_path_config.home = NULL;
|
||||
|
||||
if (has_value) {
|
||||
_Py_path_config.home = _PyMem_RawWcsdup(home);
|
||||
_Py_path_config.home = _PyMem_DefaultRawWcsdup(home);
|
||||
}
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
if (has_value && _Py_path_config.home == NULL) {
|
||||
path_out_of_memory(__func__);
|
||||
}
|
||||
|
@ -279,18 +259,13 @@ Py_SetProgramName(const wchar_t *program_name)
|
|||
{
|
||||
int has_value = program_name && program_name[0];
|
||||
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
PyMem_RawFree(_Py_path_config.program_name);
|
||||
_PyMem_DefaultRawFree(_Py_path_config.program_name);
|
||||
_Py_path_config.program_name = NULL;
|
||||
|
||||
if (has_value) {
|
||||
_Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
|
||||
_Py_path_config.program_name = _PyMem_DefaultRawWcsdup(program_name);
|
||||
}
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
if (has_value && _Py_path_config.program_name == NULL) {
|
||||
path_out_of_memory(__func__);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue