Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_import.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
5 changes: 3 additions & 2 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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. */
Expand Down
5 changes: 3 additions & 2 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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");
}
}
Expand All @@ -229,6 +229,7 @@ _PyImport_ReInitLock(void)
import_lock_level = 0;
}
}
#endif

/*[clinic input]
_imp.lock_held
Expand Down
14 changes: 8 additions & 6 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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)
Expand Down