diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 298018a872b..050dd59ed15 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -25,8 +25,9 @@ PyAPI_FUNC(int) _PyEval_AddPendingCall( int (*func)(void *), void *arg); PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate); -PyAPI_FUNC(void) _PyEval_ReInitThreads( - struct pyruntimestate *runtime); +#ifdef HAVE_FORK +extern void _PyEval_ReInitThreads(struct pyruntimestate *runtime); +#endif PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth( PyThreadState *tstate, int new_depth); diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index 5d3203e5b97..b011ea44251 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -10,7 +10,9 @@ PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin( const char *name /* UTF-8 encoded string */ ); +#ifdef HAVE_FORK extern void _PyImport_ReInitLock(void); +#endif extern void _PyImport_Cleanup(PyThreadState *tstate); #ifdef __cplusplus diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 54dbaeb77c7..995fe231c32 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -117,8 +117,9 @@ PyAPI_DATA(_PyRuntimeState) _PyRuntime; PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); +#ifdef HAVE_FORK PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); - +#endif /* Initialize _PyRuntimeState. Return NULL on success, or return an error message on failure. */ diff --git a/Python/ceval.c b/Python/ceval.c index 16e2d0b1fbe..77b7a83869e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -397,6 +397,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) drop_gil(&runtime->ceval, tstate); } +#ifdef HAVE_FORK /* 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 might be held by those threads. @@ -416,14 +417,14 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime) take_gil(tstate); struct _pending_calls *pending = &tstate->interp->ceval.pending; - pending->lock = PyThread_allocate_lock(); - if (pending->lock == NULL) { + if (_PyThread_at_fork_reinit(&pending->lock) < 0) { Py_FatalError("Can't initialize threads for pending calls"); } /* Destroy all threads except the current one */ _PyThreadState_DeleteExcept(runtime, tstate); } +#endif /* This function is used to signal that async exceptions are waiting to be raised. */ diff --git a/Python/import.c b/Python/import.c index 8a2f9de066a..49334637d67 100644 --- a/Python/import.c +++ b/Python/import.c @@ -200,6 +200,7 @@ _PyImport_ReleaseLock(void) return 1; } +#ifdef HAVE_FORK /* This function is called from PyOS_AfterFork_Child to ensure that newly created child processes do not share locks with the parent. We now acquire the import lock around fork() calls but on some platforms @@ -209,8 +210,7 @@ void _PyImport_ReInitLock(void) { if (import_lock != NULL) { - import_lock = PyThread_allocate_lock(); - if (import_lock == NULL) { + if (_PyThread_at_fork_reinit(&import_lock) < 0) { _Py_FatalErrorFunc(__func__, "failed to create a new lock"); } } @@ -229,6 +229,7 @@ _PyImport_ReInitLock(void) import_lock_level = 0; } } +#endif /*[clinic input] _imp.lock_held diff --git a/Python/pystate.c b/Python/pystate.c index 3c427c12107..d25fb3a2a62 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -132,6 +132,7 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } +#ifdef HAVE_FORK /* This function is called from PyOS_AfterFork_Child to ensure that * newly created child processes do not share locks with the parent. */ @@ -147,24 +148,25 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - runtime->interpreters.mutex = PyThread_allocate_lock(); - runtime->interpreters.main->id_mutex = PyThread_allocate_lock(); - runtime->xidregistry.mutex = PyThread_allocate_lock(); + int interp_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); + int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + int xidregistry_mutex = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); 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"); } - if (runtime->interpreters.main->id_mutex == NULL) { + if (main_interp_id_mutex < 0) { 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"); } } +#endif #define HEAD_LOCK(runtime) \ PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)