[Python-checkins] bpo-36356: Destroy the GIL at exit (GH-12453)

Victor Stinner webhook-mailer at python.org
Mon Apr 29 05:16:02 EDT 2019


https://github.com/python/cpython/commit/b36e5d627d4232a01850707eb78a5067f3fd77f4
commit: b36e5d627d4232a01850707eb78a5067f3fd77f4
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-04-29T11:15:56+02:00
summary:

bpo-36356: Destroy the GIL at exit (GH-12453)

* Add _PyEval_FiniThreads2(). _PyEval_FiniThreads() now only clears
  the pending lock, whereas _PyEval_FiniThreads2() destroys the GIL.
* pymain_free() now calls _PyEval_FiniThreads2().
* Py_FinalizeEx() now calls _PyEval_FiniThreads().

files:
M Include/ceval.h
M Include/internal/pycore_ceval.h
M Modules/main.c
M Python/ceval.c
M Python/pylifecycle.c

diff --git a/Include/ceval.h b/Include/ceval.h
index 11283c0a570b..98e873d2c8b2 100644
--- a/Include/ceval.h
+++ b/Include/ceval.h
@@ -192,9 +192,6 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
 
 PyAPI_FUNC(int)  PyEval_ThreadsInitialized(void);
 PyAPI_FUNC(void) PyEval_InitThreads(void);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _PyEval_FiniThreads(void);
-#endif /* !Py_LIMITED_API */
 PyAPI_FUNC(void) PyEval_AcquireLock(void) Py_DEPRECATED(3.2);
 PyAPI_FUNC(void) PyEval_ReleaseLock(void) /* Py_DEPRECATED(3.2) */;
 PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 0bb19f1aa3b6..ae3d83239227 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -54,6 +54,9 @@ struct _ceval_runtime_state {
 
 PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *);
 
+PyAPI_FUNC(void) _PyEval_FiniThreads(void);
+PyAPI_FUNC(void) _PyEval_FiniThreads2(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Modules/main.c b/Modules/main.c
index 68f0b99c9fbb..f77bbd2f41c4 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -1,6 +1,7 @@
 /* Python interpreter main program */
 
 #include "Python.h"
+#include "pycore_ceval.h"   /* _PyEval_FiniThreads2() */
 #include "pycore_coreconfig.h"
 #include "pycore_pylifecycle.h"
 #include "pycore_pymem.h"
@@ -525,15 +526,15 @@ pymain_run_python(int *exitcode)
 
 /* --- pymain_main() ---------------------------------------------- */
 
+/* Free global variables which cannot be freed in Py_Finalize():
+   configuration options set before Py_Initialize() which should
+   remain valid after Py_Finalize(), since
+   Py_Initialize()-Py_Finalize() can be called multiple times. */
 static void
 pymain_free(void)
 {
     _PyImport_Fini2();
-
-    /* Free global variables which cannot be freed in Py_Finalize():
-       configuration options set before Py_Initialize() which should
-       remain valid after Py_Finalize(), since
-       Py_Initialize()-Py_Finalize() can be called multiple times. */
+    _PyEval_FiniThreads2();
     _PyPathConfig_ClearGlobal();
     _Py_ClearStandardStreamEncoding();
     _Py_ClearArgcArgv();
diff --git a/Python/ceval.c b/Python/ceval.c
index ccd0427a1429..5480fbacaf4d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -188,8 +188,19 @@ PyEval_InitThreads(void)
     }
 }
 
+
 void
 _PyEval_FiniThreads(void)
+{
+    if (_PyRuntime.ceval.pending.lock != NULL) {
+        PyThread_free_lock(_PyRuntime.ceval.pending.lock);
+        _PyRuntime.ceval.pending.lock = NULL;
+    }
+}
+
+
+void
+_PyEval_FiniThreads2(void)
 {
     if (!gil_created()) {
         return;
@@ -197,11 +208,6 @@ _PyEval_FiniThreads(void)
 
     destroy_gil();
     assert(!gil_created());
-
-    if (_PyRuntime.ceval.pending.lock != NULL) {
-        PyThread_free_lock(_PyRuntime.ceval.pending.lock);
-        _PyRuntime.ceval.pending.lock = NULL;
-    }
 }
 
 static inline void
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index d93fe065558a..0836e18f9d1c 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -4,8 +4,9 @@
 
 #include "Python-ast.h"
 #undef Yield   /* undefine macro conflicting with <winbase.h> */
-#include "pycore_coreconfig.h"
+#include "pycore_ceval.h"   /* _PyEval_FiniThreads() */
 #include "pycore_context.h"
+#include "pycore_coreconfig.h"
 #include "pycore_fileutils.h"
 #include "pycore_hamt.h"
 #include "pycore_pathconfig.h"
@@ -555,12 +556,11 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
         return _Py_INIT_ERR("can't make first thread");
     (void) PyThreadState_Swap(tstate);
 
-    /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because
-       destroying the GIL might fail when it is being referenced from
-       another running thread (see issue #9901).
+    /* Destroying the GIL in Py_FinalizeEx might fail when it is being
+       referenced from another running thread (see bpo-9901).
        Instead we destroy the previously created GIL here, which ensures
        that we can call Py_Initialize / Py_FinalizeEx multiple times. */
-    _PyEval_FiniThreads();
+    _PyEval_FiniThreads2();
 
     /* Auto-thread-state API */
     _PyGILState_Init(runtime, interp, tstate);
@@ -1357,6 +1357,7 @@ Py_FinalizeEx(void)
 
     call_ll_exitfuncs(runtime);
 
+    _PyEval_FiniThreads();
     _PyRuntime_Finalize();
     return status;
 }



More information about the Python-checkins mailing list