mirror of https://github.com/python/cpython
bpo-36710: PyOS_AfterFork_Child() pass runtime parameter (GH-12936)
The PyOS_AfterFork_Child() function now pass a 'runtime' parameter to subfunctions. * Fix _PyRuntimeState_ReInitThreads(): use the correct memory allocator * Add runtime parameter to _PyRuntimeState_ReInitThreads(), _PyGILState_Reinit() and _PyInterpreterState_DeleteExceptMain() * Move _PyGILState_Reinit() to the internal C API.
This commit is contained in:
parent
8bb3230149
commit
b930a2d2b1
|
@ -155,7 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
|
||||||
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
|
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
|
||||||
PyAPI_FUNC(void) _PyState_ClearModules(void);
|
PyAPI_FUNC(void) _PyState_ClearModules(void);
|
||||||
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
|
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
|
||||||
PyAPI_FUNC(void) _PyGILState_Reinit(void);
|
|
||||||
|
|
||||||
/* Similar to PyThreadState_Get(), but don't issue a fatal error
|
/* Similar to PyThreadState_Get(), but don't issue a fatal error
|
||||||
* if it is NULL. */
|
* if it is NULL. */
|
||||||
|
|
|
@ -185,9 +185,9 @@ typedef struct pyruntimestate {
|
||||||
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
|
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
|
||||||
|
|
||||||
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
|
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
|
||||||
PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *);
|
PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *runtime);
|
||||||
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *);
|
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
|
||||||
PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(void);
|
PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
@ -236,8 +236,10 @@ PyAPI_FUNC(void) _PyThreadState_Init(
|
||||||
PyThreadState *tstate);
|
PyThreadState *tstate);
|
||||||
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
|
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
|
||||||
|
|
||||||
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
|
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
|
||||||
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void);
|
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,12 +421,13 @@ PyOS_AfterFork_Parent(void)
|
||||||
void
|
void
|
||||||
PyOS_AfterFork_Child(void)
|
PyOS_AfterFork_Child(void)
|
||||||
{
|
{
|
||||||
_PyGILState_Reinit();
|
_PyRuntimeState *runtime = &_PyRuntime;
|
||||||
_PyInterpreterState_DeleteExceptMain();
|
_PyGILState_Reinit(runtime);
|
||||||
|
_PyInterpreterState_DeleteExceptMain(runtime);
|
||||||
PyEval_ReInitThreads();
|
PyEval_ReInitThreads();
|
||||||
_PyImport_ReInitLock();
|
_PyImport_ReInitLock();
|
||||||
_PySignal_AfterFork();
|
_PySignal_AfterFork();
|
||||||
_PyRuntimeState_ReInitThreads();
|
_PyRuntimeState_ReInitThreads(runtime);
|
||||||
|
|
||||||
run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
|
run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,23 +108,31 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyRuntimeState_ReInitThreads(void)
|
_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
|
||||||
{
|
{
|
||||||
// This was initially set in _PyRuntimeState_Init().
|
// This was initially set in _PyRuntimeState_Init().
|
||||||
_PyRuntime.main_thread = PyThread_get_thread_ident();
|
runtime->main_thread = PyThread_get_thread_ident();
|
||||||
|
|
||||||
_PyRuntime.interpreters.mutex = PyThread_allocate_lock();
|
/* Force default allocator, since _PyRuntimeState_Fini() must
|
||||||
if (_PyRuntime.interpreters.mutex == NULL) {
|
use the same allocator than this function. */
|
||||||
|
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();
|
||||||
|
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
|
if (runtime->interpreters.mutex == NULL) {
|
||||||
Py_FatalError("Can't initialize lock for runtime interpreters");
|
Py_FatalError("Can't initialize lock for runtime interpreters");
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyRuntime.interpreters.main->id_mutex = PyThread_allocate_lock();
|
if (runtime->interpreters.main->id_mutex == NULL) {
|
||||||
if (_PyRuntime.interpreters.main->id_mutex == NULL) {
|
|
||||||
Py_FatalError("Can't initialize ID lock for main interpreter");
|
Py_FatalError("Can't initialize ID lock for main interpreter");
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyRuntime.xidregistry.mutex = PyThread_allocate_lock();
|
if (runtime->xidregistry.mutex == NULL) {
|
||||||
if (_PyRuntime.xidregistry.mutex == NULL) {
|
|
||||||
Py_FatalError("Can't initialize lock for cross-interpreter data registry");
|
Py_FatalError("Can't initialize lock for cross-interpreter data registry");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,20 +298,22 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
|
||||||
* is a current interpreter state, it *must* be the main interpreter.
|
* is a current interpreter state, it *must* be the main interpreter.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_PyInterpreterState_DeleteExceptMain()
|
_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
|
||||||
{
|
{
|
||||||
|
struct pyinterpreters *interpreters = &runtime->interpreters;
|
||||||
|
|
||||||
PyThreadState *tstate = PyThreadState_Swap(NULL);
|
PyThreadState *tstate = PyThreadState_Swap(NULL);
|
||||||
if (tstate != NULL && tstate->interp != _PyRuntime.interpreters.main) {
|
if (tstate != NULL && tstate->interp != interpreters->main) {
|
||||||
Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter");
|
Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter");
|
||||||
}
|
}
|
||||||
|
|
||||||
HEAD_LOCK();
|
HEAD_LOCK();
|
||||||
PyInterpreterState *interp = _PyRuntime.interpreters.head;
|
PyInterpreterState *interp = interpreters->head;
|
||||||
_PyRuntime.interpreters.head = NULL;
|
interpreters->head = NULL;
|
||||||
while (interp != NULL) {
|
while (interp != NULL) {
|
||||||
if (interp == _PyRuntime.interpreters.main) {
|
if (interp == interpreters->main) {
|
||||||
_PyRuntime.interpreters.main->next = NULL;
|
interpreters->main->next = NULL;
|
||||||
_PyRuntime.interpreters.head = interp;
|
interpreters->head = interp;
|
||||||
interp = interp->next;
|
interp = interp->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +329,7 @@ _PyInterpreterState_DeleteExceptMain()
|
||||||
}
|
}
|
||||||
HEAD_UNLOCK();
|
HEAD_UNLOCK();
|
||||||
|
|
||||||
if (_PyRuntime.interpreters.head == NULL) {
|
if (interpreters->head == NULL) {
|
||||||
Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main");
|
Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main");
|
||||||
}
|
}
|
||||||
PyThreadState_Swap(tstate);
|
PyThreadState_Swap(tstate);
|
||||||
|
@ -1079,31 +1089,20 @@ _PyGILState_Fini(void)
|
||||||
* don't reset TSS upon fork(), see issue #10517.
|
* don't reset TSS upon fork(), see issue #10517.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_PyGILState_Reinit(void)
|
_PyGILState_Reinit(_PyRuntimeState *runtime)
|
||||||
{
|
{
|
||||||
/* Force default allocator, since _PyRuntimeState_Fini() must
|
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
|
||||||
use the same allocator than this function. */
|
|
||||||
PyMemAllocatorEx old_alloc;
|
|
||||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
||||||
|
|
||||||
_PyRuntime.interpreters.mutex = PyThread_allocate_lock();
|
|
||||||
|
|
||||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
||||||
|
|
||||||
if (_PyRuntime.interpreters.mutex == NULL) {
|
|
||||||
Py_FatalError("Can't initialize threads for interpreter");
|
|
||||||
}
|
|
||||||
|
|
||||||
PyThreadState *tstate = PyGILState_GetThisThreadState();
|
PyThreadState *tstate = PyGILState_GetThisThreadState();
|
||||||
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
|
|
||||||
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
|
PyThread_tss_delete(&gilstate->autoTSSkey);
|
||||||
|
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
|
||||||
Py_FatalError("Could not allocate TSS entry");
|
Py_FatalError("Could not allocate TSS entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the thread had an associated auto thread state, reassociate it with
|
/* If the thread had an associated auto thread state, reassociate it with
|
||||||
* the new key. */
|
* the new key. */
|
||||||
if (tstate &&
|
if (tstate &&
|
||||||
PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) != 0)
|
PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0)
|
||||||
{
|
{
|
||||||
Py_FatalError("Couldn't create autoTSSkey mapping");
|
Py_FatalError("Couldn't create autoTSSkey mapping");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue