[Python-checkins] bpo-36710: PyOS_AfterFork_Child() pass runtime parameter (GH-12936)

Victor Stinner webhook-mailer at python.org
Wed Apr 24 11:18:42 EDT 2019


https://github.com/python/cpython/commit/b930a2d2b1247bdba560db341ba90a9cbb538eb3
commit: b930a2d2b1247bdba560db341ba90a9cbb538eb3
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-04-24T17:14:33+02:00
summary:

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.

files:
M Include/cpython/pystate.h
M Include/internal/pycore_pystate.h
M Modules/posixmodule.c
M Python/pystate.c

diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index 2341dda3fabd..94331f35e1bd 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -155,7 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
 PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
 PyAPI_FUNC(void) _PyState_ClearModules(void);
 PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
-PyAPI_FUNC(void) _PyGILState_Reinit(void);
 
 /* Similar to PyThreadState_Get(), but don't issue a fatal error
  * if it is NULL. */
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index 509ca3634a3a..2c24f679dc02 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -185,9 +185,9 @@ typedef struct pyruntimestate {
 /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
 
 PyAPI_DATA(_PyRuntimeState) _PyRuntime;
-PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *);
-PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *);
-PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(void);
+PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *runtime);
+PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
+PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
 
 /* Initialize _PyRuntimeState.
    Return NULL on success, or return an error message on failure. */
@@ -236,8 +236,10 @@ PyAPI_FUNC(void) _PyThreadState_Init(
     PyThreadState *tstate);
 PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
 
-PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
-PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void);
+PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
+PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
+
+PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
 
 #ifdef __cplusplus
 }
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index e8dbdcc94aa7..56ec3ee5a0ee 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -421,12 +421,13 @@ PyOS_AfterFork_Parent(void)
 void
 PyOS_AfterFork_Child(void)
 {
-    _PyGILState_Reinit();
-    _PyInterpreterState_DeleteExceptMain();
+    _PyRuntimeState *runtime = &_PyRuntime;
+    _PyGILState_Reinit(runtime);
+    _PyInterpreterState_DeleteExceptMain(runtime);
     PyEval_ReInitThreads();
     _PyImport_ReInitLock();
     _PySignal_AfterFork();
-    _PyRuntimeState_ReInitThreads();
+    _PyRuntimeState_ReInitThreads(runtime);
 
     run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
 }
diff --git a/Python/pystate.c b/Python/pystate.c
index ef9d79288736..6aaf993cfe2c 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -108,23 +108,31 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
  */
 
 void
-_PyRuntimeState_ReInitThreads(void)
+_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
 {
     // This was initially set in _PyRuntimeState_Init().
-    _PyRuntime.main_thread = PyThread_get_thread_ident();
+    runtime->main_thread = PyThread_get_thread_ident();
+
+    /* Force default allocator, since _PyRuntimeState_Fini() must
+       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);
 
-    _PyRuntime.interpreters.mutex = PyThread_allocate_lock();
-    if (_PyRuntime.interpreters.mutex == NULL) {
+    if (runtime->interpreters.mutex == NULL) {
         Py_FatalError("Can't initialize lock for runtime interpreters");
     }
 
-    _PyRuntime.interpreters.main->id_mutex = PyThread_allocate_lock();
-    if (_PyRuntime.interpreters.main->id_mutex == NULL) {
+    if (runtime->interpreters.main->id_mutex == NULL) {
         Py_FatalError("Can't initialize ID lock for main interpreter");
     }
 
-    _PyRuntime.xidregistry.mutex = PyThread_allocate_lock();
-    if (_PyRuntime.xidregistry.mutex == NULL) {
+    if (runtime->xidregistry.mutex == NULL) {
         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.
  */
 void
-_PyInterpreterState_DeleteExceptMain()
+_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
 {
+    struct pyinterpreters *interpreters = &runtime->interpreters;
+
     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");
     }
 
     HEAD_LOCK();
-    PyInterpreterState *interp = _PyRuntime.interpreters.head;
-    _PyRuntime.interpreters.head = NULL;
+    PyInterpreterState *interp = interpreters->head;
+    interpreters->head = NULL;
     while (interp != NULL) {
-        if (interp == _PyRuntime.interpreters.main) {
-            _PyRuntime.interpreters.main->next = NULL;
-            _PyRuntime.interpreters.head = interp;
+        if (interp == interpreters->main) {
+            interpreters->main->next = NULL;
+            interpreters->head = interp;
             interp = interp->next;
             continue;
         }
@@ -319,7 +329,7 @@ _PyInterpreterState_DeleteExceptMain()
     }
     HEAD_UNLOCK();
 
-    if (_PyRuntime.interpreters.head == NULL) {
+    if (interpreters->head == NULL) {
         Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main");
     }
     PyThreadState_Swap(tstate);
@@ -1079,31 +1089,20 @@ _PyGILState_Fini(void)
  * don't reset TSS upon fork(), see issue #10517.
  */
 void
-_PyGILState_Reinit(void)
+_PyGILState_Reinit(_PyRuntimeState *runtime)
 {
-    /* Force default allocator, since _PyRuntimeState_Fini() must
-       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");
-    }
-
+    struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
     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");
     }
 
     /* If the thread had an associated auto thread state, reassociate it with
      * the new key. */
     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");
     }



More information about the Python-checkins mailing list