Skip to content

Commit b930a2d

Browse files
authored
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.
1 parent 8bb3230 commit b930a2d

File tree

4 files changed

+43
-42
lines changed

4 files changed

+43
-42
lines changed

‎Include/cpython/pystate.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
155155
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
156156
PyAPI_FUNC(void) _PyState_ClearModules(void);
157157
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
158-
PyAPI_FUNC(void) _PyGILState_Reinit(void);
159158

160159
/* Similar to PyThreadState_Get(), but don't issue a fatal error
161160
* if it is NULL. */

‎Include/internal/pycore_pystate.h‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ typedef struct pyruntimestate {
185185
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
186186

187187
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
188-
PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *);
189-
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *);
190-
PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(void);
188+
PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *runtime);
189+
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
190+
PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
191191

192192
/* Initialize _PyRuntimeState.
193193
Return NULL on success, or return an error message on failure. */
@@ -236,8 +236,10 @@ PyAPI_FUNC(void) _PyThreadState_Init(
236236
PyThreadState *tstate);
237237
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
238238

239-
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
240-
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void);
239+
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
240+
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
241+
242+
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
241243

242244
#ifdef __cplusplus
243245
}

‎Modules/posixmodule.c‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,13 @@ PyOS_AfterFork_Parent(void)
421421
void
422422
PyOS_AfterFork_Child(void)
423423
{
424-
_PyGILState_Reinit();
425-
_PyInterpreterState_DeleteExceptMain();
424+
_PyRuntimeState *runtime = &_PyRuntime;
425+
_PyGILState_Reinit(runtime);
426+
_PyInterpreterState_DeleteExceptMain(runtime);
426427
PyEval_ReInitThreads();
427428
_PyImport_ReInitLock();
428429
_PySignal_AfterFork();
429-
_PyRuntimeState_ReInitThreads();
430+
_PyRuntimeState_ReInitThreads(runtime);
430431

431432
run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
432433
}

‎Python/pystate.c‎

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -108,23 +108,31 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
108108
*/
109109

110110
void
111-
_PyRuntimeState_ReInitThreads(void)
111+
_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
112112
{
113113
// This was initially set in _PyRuntimeState_Init().
114-
_PyRuntime.main_thread = PyThread_get_thread_ident();
114+
runtime->main_thread = PyThread_get_thread_ident();
115+
116+
/* Force default allocator, since _PyRuntimeState_Fini() must
117+
use the same allocator than this function. */
118+
PyMemAllocatorEx old_alloc;
119+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
120+
121+
runtime->interpreters.mutex = PyThread_allocate_lock();
122+
runtime->interpreters.main->id_mutex = PyThread_allocate_lock();
123+
runtime->xidregistry.mutex = PyThread_allocate_lock();
124+
125+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
115126

116-
_PyRuntime.interpreters.mutex = PyThread_allocate_lock();
117-
if (_PyRuntime.interpreters.mutex == NULL) {
127+
if (runtime->interpreters.mutex == NULL) {
118128
Py_FatalError("Can't initialize lock for runtime interpreters");
119129
}
120130

121-
_PyRuntime.interpreters.main->id_mutex = PyThread_allocate_lock();
122-
if (_PyRuntime.interpreters.main->id_mutex == NULL) {
131+
if (runtime->interpreters.main->id_mutex == NULL) {
123132
Py_FatalError("Can't initialize ID lock for main interpreter");
124133
}
125134

126-
_PyRuntime.xidregistry.mutex = PyThread_allocate_lock();
127-
if (_PyRuntime.xidregistry.mutex == NULL) {
135+
if (runtime->xidregistry.mutex == NULL) {
128136
Py_FatalError("Can't initialize lock for cross-interpreter data registry");
129137
}
130138
}
@@ -290,20 +298,22 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
290298
* is a current interpreter state, it *must* be the main interpreter.
291299
*/
292300
void
293-
_PyInterpreterState_DeleteExceptMain()
301+
_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
294302
{
303+
struct pyinterpreters *interpreters = &runtime->interpreters;
304+
295305
PyThreadState *tstate = PyThreadState_Swap(NULL);
296-
if (tstate != NULL && tstate->interp != _PyRuntime.interpreters.main) {
306+
if (tstate != NULL && tstate->interp != interpreters->main) {
297307
Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter");
298308
}
299309

300310
HEAD_LOCK();
301-
PyInterpreterState *interp = _PyRuntime.interpreters.head;
302-
_PyRuntime.interpreters.head = NULL;
311+
PyInterpreterState *interp = interpreters->head;
312+
interpreters->head = NULL;
303313
while (interp != NULL) {
304-
if (interp == _PyRuntime.interpreters.main) {
305-
_PyRuntime.interpreters.main->next = NULL;
306-
_PyRuntime.interpreters.head = interp;
314+
if (interp == interpreters->main) {
315+
interpreters->main->next = NULL;
316+
interpreters->head = interp;
307317
interp = interp->next;
308318
continue;
309319
}
@@ -319,7 +329,7 @@ _PyInterpreterState_DeleteExceptMain()
319329
}
320330
HEAD_UNLOCK();
321331

322-
if (_PyRuntime.interpreters.head == NULL) {
332+
if (interpreters->head == NULL) {
323333
Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main");
324334
}
325335
PyThreadState_Swap(tstate);
@@ -1079,31 +1089,20 @@ _PyGILState_Fini(void)
10791089
* don't reset TSS upon fork(), see issue #10517.
10801090
*/
10811091
void
1082-
_PyGILState_Reinit(void)
1092+
_PyGILState_Reinit(_PyRuntimeState *runtime)
10831093
{
1084-
/* Force default allocator, since _PyRuntimeState_Fini() must
1085-
use the same allocator than this function. */
1086-
PyMemAllocatorEx old_alloc;
1087-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1088-
1089-
_PyRuntime.interpreters.mutex = PyThread_allocate_lock();
1090-
1091-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1092-
1093-
if (_PyRuntime.interpreters.mutex == NULL) {
1094-
Py_FatalError("Can't initialize threads for interpreter");
1095-
}
1096-
1094+
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
10971095
PyThreadState *tstate = PyGILState_GetThisThreadState();
1098-
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
1099-
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
1096+
1097+
PyThread_tss_delete(&gilstate->autoTSSkey);
1098+
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
11001099
Py_FatalError("Could not allocate TSS entry");
11011100
}
11021101

11031102
/* If the thread had an associated auto thread state, reassociate it with
11041103
* the new key. */
11051104
if (tstate &&
1106-
PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) != 0)
1105+
PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0)
11071106
{
11081107
Py_FatalError("Couldn't create autoTSSkey mapping");
11091108
}

0 commit comments

Comments
 (0)