bpo-33005: Fix _PyGILState_Reinit() (GH-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.
(cherry picked from commit 5d92647102)

Co-authored-by: Victor Stinner <victor.stinner@gmail.com>
This commit is contained in:
Miss Islington (bot) 2018-03-06 05:52:27 -08:00 committed by GitHub
parent 96fdbacb77
commit 31e2b76f7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 4 deletions

View file

@ -0,0 +1,4 @@
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.

View file

@ -103,15 +103,24 @@ _PyInitError
_PyInterpreterState_Enable(_PyRuntimeState *runtime) _PyInterpreterState_Enable(_PyRuntimeState *runtime)
{ {
runtime->interpreters.next_id = 0; runtime->interpreters.next_id = 0;
/* Since we only call _PyRuntimeState_Init() once per process
(see _PyRuntime_Initialize()), we make sure the mutex is /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
initialized here. */ Create a new mutex if needed. */
if (runtime->interpreters.mutex == NULL) { if (runtime->interpreters.mutex == NULL) {
/* Force default allocator, since _PyRuntimeState_Fini() must
use the same allocator than this function. */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
runtime->interpreters.mutex = PyThread_allocate_lock(); runtime->interpreters.mutex = PyThread_allocate_lock();
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (runtime->interpreters.mutex == NULL) { if (runtime->interpreters.mutex == NULL) {
return _Py_INIT_ERR("Can't initialize threads for interpreter"); return _Py_INIT_ERR("Can't initialize threads for interpreter");
} }
} }
return _Py_INIT_OK(); return _Py_INIT_OK();
} }
@ -933,9 +942,19 @@ _PyGILState_Fini(void)
void void
_PyGILState_Reinit(void) _PyGILState_Reinit(void)
{ {
/* Force default allocator, since _PyRuntimeState_Fini() must
use the same allocator than this function. */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
_PyRuntime.interpreters.mutex = PyThread_allocate_lock(); _PyRuntime.interpreters.mutex = PyThread_allocate_lock();
if (_PyRuntime.interpreters.mutex == NULL)
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_PyRuntime.interpreters.mutex == NULL) {
Py_FatalError("Can't initialize threads for interpreter"); Py_FatalError("Can't initialize threads for interpreter");
}
PyThreadState *tstate = PyGILState_GetThisThreadState(); PyThreadState *tstate = PyGILState_GetThisThreadState();
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {