bpo-40232: Update PyOS_AfterFork_Child() to use _PyThread_at_fork_reinit() (GH-19450)

This commit is contained in:
Dong-hee Na 2020-04-15 01:16:24 +09:00 committed by GitHub
parent e5014be049
commit 62f75fe3dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 21 additions and 13 deletions

View File

@ -25,8 +25,9 @@ PyAPI_FUNC(int) _PyEval_AddPendingCall(
int (*func)(void *), int (*func)(void *),
void *arg); void *arg);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate); PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate);
PyAPI_FUNC(void) _PyEval_ReInitThreads( #ifdef HAVE_FORK
struct pyruntimestate *runtime); extern void _PyEval_ReInitThreads(struct pyruntimestate *runtime);
#endif
PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth( PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(
PyThreadState *tstate, PyThreadState *tstate,
int new_depth); int new_depth);

View File

@ -10,7 +10,9 @@ PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin(
const char *name /* UTF-8 encoded string */ const char *name /* UTF-8 encoded string */
); );
#ifdef HAVE_FORK
extern void _PyImport_ReInitLock(void); extern void _PyImport_ReInitLock(void);
#endif
extern void _PyImport_Cleanup(PyThreadState *tstate); extern void _PyImport_Cleanup(PyThreadState *tstate);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -117,8 +117,9 @@ PyAPI_DATA(_PyRuntimeState) _PyRuntime;
PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime); PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime);
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
#ifdef HAVE_FORK
PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
#endif
/* Initialize _PyRuntimeState. /* Initialize _PyRuntimeState.
Return NULL on success, or return an error message on failure. */ Return NULL on success, or return an error message on failure. */

View File

@ -397,6 +397,7 @@ PyEval_ReleaseThread(PyThreadState *tstate)
drop_gil(&runtime->ceval, tstate); drop_gil(&runtime->ceval, tstate);
} }
#ifdef HAVE_FORK
/* This function is called from PyOS_AfterFork_Child to destroy all threads /* This function is called from PyOS_AfterFork_Child to destroy all threads
* which are not running in the child process, and clear internal locks * which are not running in the child process, and clear internal locks
* which might be held by those threads. * which might be held by those threads.
@ -416,14 +417,14 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime)
take_gil(tstate); take_gil(tstate);
struct _pending_calls *pending = &tstate->interp->ceval.pending; struct _pending_calls *pending = &tstate->interp->ceval.pending;
pending->lock = PyThread_allocate_lock(); if (_PyThread_at_fork_reinit(&pending->lock) < 0) {
if (pending->lock == NULL) {
Py_FatalError("Can't initialize threads for pending calls"); Py_FatalError("Can't initialize threads for pending calls");
} }
/* Destroy all threads except the current one */ /* Destroy all threads except the current one */
_PyThreadState_DeleteExcept(runtime, tstate); _PyThreadState_DeleteExcept(runtime, tstate);
} }
#endif
/* This function is used to signal that async exceptions are waiting to be /* This function is used to signal that async exceptions are waiting to be
raised. */ raised. */

View File

@ -200,6 +200,7 @@ _PyImport_ReleaseLock(void)
return 1; return 1;
} }
#ifdef HAVE_FORK
/* This function is called from PyOS_AfterFork_Child to ensure that newly /* This function is called from PyOS_AfterFork_Child to ensure that newly
created child processes do not share locks with the parent. created child processes do not share locks with the parent.
We now acquire the import lock around fork() calls but on some platforms We now acquire the import lock around fork() calls but on some platforms
@ -209,8 +210,7 @@ void
_PyImport_ReInitLock(void) _PyImport_ReInitLock(void)
{ {
if (import_lock != NULL) { if (import_lock != NULL) {
import_lock = PyThread_allocate_lock(); if (_PyThread_at_fork_reinit(&import_lock) < 0) {
if (import_lock == NULL) {
_Py_FatalErrorFunc(__func__, "failed to create a new lock"); _Py_FatalErrorFunc(__func__, "failed to create a new lock");
} }
} }
@ -229,6 +229,7 @@ _PyImport_ReInitLock(void)
import_lock_level = 0; import_lock_level = 0;
} }
} }
#endif
/*[clinic input] /*[clinic input]
_imp.lock_held _imp.lock_held

View File

@ -132,6 +132,7 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
} }
#ifdef HAVE_FORK
/* This function is called from PyOS_AfterFork_Child to ensure that /* This function is called from PyOS_AfterFork_Child to ensure that
* newly created child processes do not share locks with the parent. * newly created child processes do not share locks with the parent.
*/ */
@ -147,24 +148,25 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
PyMemAllocatorEx old_alloc; PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
runtime->interpreters.mutex = PyThread_allocate_lock(); int interp_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
runtime->interpreters.main->id_mutex = PyThread_allocate_lock(); int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
runtime->xidregistry.mutex = PyThread_allocate_lock(); int xidregistry_mutex = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (runtime->interpreters.mutex == NULL) { if (interp_mutex < 0) {
Py_FatalError("Can't initialize lock for runtime interpreters"); Py_FatalError("Can't initialize lock for runtime interpreters");
} }
if (runtime->interpreters.main->id_mutex == NULL) { if (main_interp_id_mutex < 0) {
Py_FatalError("Can't initialize ID lock for main interpreter"); Py_FatalError("Can't initialize ID lock for main interpreter");
} }
if (runtime->xidregistry.mutex == NULL) { if (xidregistry_mutex < 0) {
Py_FatalError("Can't initialize lock for cross-interpreter data registry"); Py_FatalError("Can't initialize lock for cross-interpreter data registry");
} }
} }
#endif
#define HEAD_LOCK(runtime) \ #define HEAD_LOCK(runtime) \
PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)