Skip to content

Commit

Permalink
bpo-40232: Update PyOS_AfterFork_Child() to use _PyThread_at_fork_rei…
Browse files Browse the repository at this point in the history
…nit() (pythonGH-19450)
  • Loading branch information
corona10 authored Apr 14, 2020
1 parent e5014be commit 62f75fe
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 13 deletions.
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

0 comments on commit 62f75fe

Please sign in to comment.