[Python-checkins] cpython: Add more checks on the GIL

victor.stinner python-checkins at python.org
Mon Mar 14 17:49:58 EDT 2016


https://hg.python.org/cpython/rev/e590c632c9fa
changeset:   100537:e590c632c9fa
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Mon Mar 14 22:07:55 2016 +0100
summary:
  Add more checks on the GIL

Issue #10915, #15751, #26558:

* PyGILState_Check() now returns 1 (success) before the creation of the GIL and
  after the destruction of the GIL. It allows to use the function early in
  Python initialization and late in Python finalization.
* Add a flag to disable PyGILState_Check(). Disable PyGILState_Check() when
  Py_NewInterpreter() is called
* Add assert(PyGILState_Check()) to: _Py_dup(), _Py_fstat(), _Py_read()
  and _Py_write()

files:
  Include/pystate.h    |   4 ++++
  Parser/pgenmain.c    |   8 ++++++++
  Python/fileutils.c   |  16 ++++++++++++++++
  Python/pylifecycle.c |   5 +++++
  Python/pystate.c     |  24 +++++++++++++++++++-----
  5 files changed, 52 insertions(+), 5 deletions(-)


diff --git a/Include/pystate.h b/Include/pystate.h
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -247,6 +247,10 @@
  * currently holds the GIL, 0 otherwise
  */
 #ifndef Py_LIMITED_API
+/* Issue #26558: Flag to disable PyGILState_Check().
+   If set, PyGILState_Check() always return 1. */
+PyAPI_DATA(int) _PyGILState_check_enabled;
+
 PyAPI_FUNC(int) PyGILState_Check(void);
 #endif
 
diff --git a/Parser/pgenmain.c b/Parser/pgenmain.c
--- a/Parser/pgenmain.c
+++ b/Parser/pgenmain.c
@@ -37,6 +37,14 @@
     exit(sts);
 }
 
+#ifdef WITH_THREAD
+/* Needed by obmalloc.c */
+int PyGILState_Check(void)
+{
+    return 1;
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
diff --git a/Python/fileutils.c b/Python/fileutils.c
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -683,6 +683,10 @@
 {
     int res;
 
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+
     Py_BEGIN_ALLOW_THREADS
     res = _Py_fstat_noraise(fd, status);
     Py_END_ALLOW_THREADS
@@ -1164,6 +1168,10 @@
     int err;
     int async_err = 0;
 
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+
     /* _Py_read() must not be called with an exception set, otherwise the
      * caller may think that read() was interrupted by a signal and the signal
      * handler raised an exception. */
@@ -1319,6 +1327,10 @@
 Py_ssize_t
 _Py_write(int fd, const void *buf, size_t count)
 {
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+
     /* _Py_write() must not be called with an exception set, otherwise the
      * caller may think that write() was interrupted by a signal and the signal
      * handler raised an exception. */
@@ -1468,6 +1480,10 @@
     DWORD ftype;
 #endif
 
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+
     if (!_PyVerify_fd(fd)) {
         PyErr_SetFromErrno(PyExc_OSError);
         return -1;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -692,6 +692,7 @@
 
     /* Delete current thread. After this, many C API calls become crashy. */
     PyThreadState_Swap(NULL);
+
     PyInterpreterState_Delete(interp);
 
 #ifdef Py_TRACE_REFS
@@ -743,6 +744,10 @@
     if (!initialized)
         Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
 
+    /* Issue #10915, #15751: The GIL API doesn't work with multiple
+       interpreters: disable PyGILState_Check(). */
+    _PyGILState_check_enabled = 0;
+
     interp = PyInterpreterState_New();
     if (interp == NULL)
         return NULL;
diff --git a/Python/pystate.c b/Python/pystate.c
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -34,6 +34,8 @@
 extern "C" {
 #endif
 
+int _PyGILState_check_enabled = 1;
+
 #ifdef WITH_THREAD
 #include "pythread.h"
 static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
@@ -45,7 +47,7 @@
    GILState implementation
 */
 static PyInterpreterState *autoInterpreterState = NULL;
-static int autoTLSkey = 0;
+static int autoTLSkey = -1;
 #else
 #define HEAD_INIT() /* Nothing */
 #define HEAD_LOCK() /* Nothing */
@@ -449,10 +451,10 @@
     if (tstate == NULL)
         Py_FatalError(
             "PyThreadState_DeleteCurrent: no current tstate");
-    SET_TSTATE(NULL);
+    tstate_delete_common(tstate);
     if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
         PyThread_delete_key_value(autoTLSkey);
-    tstate_delete_common(tstate);
+    SET_TSTATE(NULL);
     PyEval_ReleaseLock();
 }
 #endif /* WITH_THREAD */
@@ -716,6 +718,7 @@
 _PyGILState_Fini(void)
 {
     PyThread_delete_key(autoTLSkey);
+    autoTLSkey = -1;
     autoInterpreterState = NULL;
 }
 
@@ -784,8 +787,19 @@
 int
 PyGILState_Check(void)
 {
-    PyThreadState *tstate = GET_TSTATE();
-    return tstate && (tstate == PyGILState_GetThisThreadState());
+    PyThreadState *tstate;
+
+    if (!_PyGILState_check_enabled)
+        return 1;
+
+    if (autoTLSkey == -1)
+        return 1;
+
+    tstate = GET_TSTATE();
+    if (tstate == NULL)
+        return 0;
+
+    return (tstate == PyGILState_GetThisThreadState());
 }
 
 PyGILState_STATE

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list