-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid changing the PYMEM_DOMAIN_RAW allocator during initialization and finalization #111924
Comments
cc @vstinner and @ericsnowcurrently in case you are interested in this. |
I'm a little unclear on this. Nearly all of the C-API is unavailable until global runtime initialization finishes and reverts to that state almost as soon as finalization begins. At both of those points only the main thread should be running. 12 Consequently, switching the raw allocator during init/fini shouldn't cause any problems. Thus I'm not sure where the problem is. Also, just to be clear, we do the raw allocator dance during init/fini for more than just locks. 3 All of that happens during global init/fini so the same single-threaded situation applies. Of course, the actual operation of changing the allocator is thread-safe, protected by one of the global locks. Hence, what we do in Python/tracemalloc.c (e.g. Footnotes
|
FWIW, I'm on board with switching the various global locks to |
"Nearly all of the C-API" here notably does not include
This is not the case during finalization. As you mention, daemon threads may still be running. So can any thread created by C (i.e., outside the Any of these threads and (random C) code may call
Yeah, those are what I was referring to in the "Calls to PyMem_RawMalloc, PyMem_RawCalloc, PyMem_RawFree, etc." section. |
Great! I'll probably tackle that part first, both because we seem to be on the same page there and it'll keep the PRs smaller. |
This replaces some usages of PyThread_type_lock with PyMutex, which does not require memory allocation to initialize.
This replaces some usages of PyThread_type_lock with PyMutex, which does not require memory allocation to initialize. This simplifies some of the runtime initialization and is also one step towards avoiding changing the default raw memory allocator during initialize/finalization, which can be non-thread-safe in some circumstances.
This replaces some usages of PyThread_type_lock with PyMutex, which does not require memory allocation to initialize. This simplifies some of the runtime initialization and is also one step towards avoiding changing the default raw memory allocator during initialize/finalization, which can be non-thread-safe in some circumstances.
This replaces some usages of PyThread_type_lock with PyMutex, which does not require memory allocation to initialize. This simplifies some of the runtime initialization and is also one step towards avoiding changing the default raw memory allocator during initialize/finalization, which can be non-thread-safe in some circumstances.
Bug report
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 usePYMEM_DOMAIN_RAW
; they are not required to hold the GIL to callPyMem_RawMalloc
/PyMem_RawFree
.We can avoid changing global state while still ensuring that we use a consistent allocator during initialization and shutdown.
PyThread_type_lock
Many of the runtime structures are
PyThread_type_lock
objects. We can avoid allocation/freeing entirely for these locks by usingPyMutex
orPyRawMutex
instead.cpython/Python/pystate.c
Lines 396 to 418 in b9f814c
Calls to
PyMem_RawMalloc
,PyMem_RawCalloc
,PyMem_RawFree
, etc.For the other calls to
PyMem_RawMalloc
, etc. where we know we want to use the default allocator, we should directly call a new internal-only function that always uses the default allocator. This will avoid unnecessarily modifying global state.For example, we can add a new function
_PyMem_DefaultRawMalloc
that behaves likePyMem_RawMalloc
, except that it is not modifiable by_PyMem_SetDefaultAllocator
.For an example implementation in the nogil-3.12 fork, see colesbury/nogil-3.12@d13c63dee9.
Linked PRs
The text was updated successfully, but these errors were encountered: