mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +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
|
@ -55,13 +55,6 @@ struct _Py_mem_interp_free_queue {
|
|||
struct llist_node head; // queue of _mem_work_chunk items
|
||||
};
|
||||
|
||||
/* Set the memory allocator of the specified domain to the default.
|
||||
Save the old allocator into *old_alloc if it's non-NULL.
|
||||
Return on success, or return -1 if the domain is unknown. */
|
||||
extern int _PyMem_SetDefaultAllocator(
|
||||
PyMemAllocatorDomain domain,
|
||||
PyMemAllocatorEx *old_alloc);
|
||||
|
||||
/* Special bytes broadcast into debug memory blocks at appropriate times.
|
||||
Strings of these are unlikely to be valid addresses, floats, ints or
|
||||
7-bit ASCII.
|
||||
|
@ -113,6 +106,13 @@ extern int _PyMem_GetAllocatorName(
|
|||
PYMEM_ALLOCATOR_NOT_SET does nothing. */
|
||||
extern int _PyMem_SetupAllocators(PyMemAllocatorName allocator);
|
||||
|
||||
// Default raw memory allocator that is not affected by PyMem_SetAllocator()
|
||||
extern void *_PyMem_DefaultRawMalloc(size_t);
|
||||
extern void *_PyMem_DefaultRawCalloc(size_t, size_t);
|
||||
extern void *_PyMem_DefaultRawRealloc(void *, size_t);
|
||||
extern void _PyMem_DefaultRawFree(void *);
|
||||
extern wchar_t *_PyMem_DefaultRawWcsdup(const wchar_t *str);
|
||||
|
||||
/* Is the debug allocator enabled? */
|
||||
extern int _PyMem_DebugEnabled(void);
|
||||
|
||||
|
@ -132,7 +132,6 @@ static inline void _PyObject_XDecRefDelayed(PyObject *obj)
|
|||
// Periodically process delayed free requests.
|
||||
extern void _PyMem_ProcessDelayed(PyThreadState *tstate);
|
||||
|
||||
|
||||
// Periodically process delayed free requests when the world is stopped.
|
||||
// Notify of any objects whic should be freeed.
|
||||
typedef void (*delayed_dealloc_cb)(PyObject *, void *);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue