Skip to content

Commit 5d92647

Browse files
authored
bpo-33005: Fix _PyGILState_Reinit() (python#6001)
Fix a crash on fork when using a custom memory allocator (ex: using PYTHONMALLOC env var). _PyGILState_Reinit() and _PyInterpreterState_Enable() now use the default RAW memory allocator to allocate a new interpreters mutex on fork.
1 parent efd2bac commit 5d92647

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a crash on fork when using a custom memory allocator (ex: using
2+
PYTHONMALLOC env var). _PyGILState_Reinit() and _PyInterpreterState_Enable()
3+
now use the default RAW memory allocator to allocate a new interpreters mutex
4+
on fork.

Python/pystate.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,24 @@ _PyInitError
103103
_PyInterpreterState_Enable(_PyRuntimeState *runtime)
104104
{
105105
runtime->interpreters.next_id = 0;
106-
/* Since we only call _PyRuntimeState_Init() once per process
107-
(see _PyRuntime_Initialize()), we make sure the mutex is
108-
initialized here. */
106+
107+
/* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
108+
Create a new mutex if needed. */
109109
if (runtime->interpreters.mutex == NULL) {
110+
/* Force default allocator, since _PyRuntimeState_Fini() must
111+
use the same allocator than this function. */
112+
PyMemAllocatorEx old_alloc;
113+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
114+
110115
runtime->interpreters.mutex = PyThread_allocate_lock();
116+
117+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
118+
111119
if (runtime->interpreters.mutex == NULL) {
112120
return _Py_INIT_ERR("Can't initialize threads for interpreter");
113121
}
114122
}
123+
115124
return _Py_INIT_OK();
116125
}
117126

@@ -933,9 +942,19 @@ _PyGILState_Fini(void)
933942
void
934943
_PyGILState_Reinit(void)
935944
{
945+
/* Force default allocator, since _PyRuntimeState_Fini() must
946+
use the same allocator than this function. */
947+
PyMemAllocatorEx old_alloc;
948+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
949+
936950
_PyRuntime.interpreters.mutex = PyThread_allocate_lock();
937-
if (_PyRuntime.interpreters.mutex == NULL)
951+
952+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
953+
954+
if (_PyRuntime.interpreters.mutex == NULL) {
938955
Py_FatalError("Can't initialize threads for interpreter");
956+
}
957+
939958
PyThreadState *tstate = PyGILState_GetThisThreadState();
940959
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
941960
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {

0 commit comments

Comments
 (0)