mirror of https://github.com/python/cpython
bpo-40232: Update PyOS_AfterFork_Child() to use _PyThread_at_fork_reinit() (GH-19450)
This commit is contained in:
parent
e5014be049
commit
62f75fe3dd
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue