]> granicus.if.org Git - python/commitdiff
Add more checks on the GIL
authorVictor Stinner <victor.stinner@gmail.com>
Mon, 14 Mar 2016 21:07:55 +0000 (22:07 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Mon, 14 Mar 2016 21:07:55 +0000 (22:07 +0100)
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()

Include/pystate.h
Parser/pgenmain.c
Python/fileutils.c
Python/pylifecycle.c
Python/pystate.c

index b50b16b39c0a09a03b515bcef2e22994b1228472..550c332cb6903dfeb35f436356d1159220c75c7d 100644 (file)
@@ -247,6 +247,10 @@ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void);
  * 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
 
index 3ca4afefd38cb80cffe4718b7269ea6396239251..671a0cb1dfe401e12057bb8380f2b6ea42d41f7f 100644 (file)
@@ -37,6 +37,14 @@ Py_Exit(int sts)
     exit(sts);
 }
 
+#ifdef WITH_THREAD
+/* Needed by obmalloc.c */
+int PyGILState_Check(void)
+{
+    return 1;
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
index 06d632a28e6236ba557289246a5e2a894184c807..a710c99129442ae7ebaacb16631164d222e0b61b 100644 (file)
@@ -683,6 +683,10 @@ _Py_fstat(int fd, struct _Py_stat_struct *status)
 {
     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 @@ _Py_read(int fd, void *buf, size_t count)
     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_write_impl(int fd, const void *buf, size_t count, int gil_held)
 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 @@ _Py_dup(int fd)
     DWORD ftype;
 #endif
 
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+
     if (!_PyVerify_fd(fd)) {
         PyErr_SetFromErrno(PyExc_OSError);
         return -1;
index aaf58119e501cff3f225d43c9542dd2a08bda62d..4fc6a1596f30ac2a8b2a74d23d08a705a541f450 100644 (file)
@@ -692,6 +692,7 @@ Py_FinalizeEx(void)
 
     /* 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 @@ Py_NewInterpreter(void)
     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;
index 853e5c746d01e00e8fe4553a090d5203afcbd7b4..e8026c52f0150163e80aed33d73f369e06c291a4 100644 (file)
@@ -34,6 +34,8 @@ to avoid the expense of doing their own locking).
 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 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
    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 @@ PyThreadState_DeleteCurrent()
     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 @@ void
 _PyGILState_Fini(void)
 {
     PyThread_delete_key(autoTLSkey);
+    autoTLSkey = -1;
     autoInterpreterState = NULL;
 }
 
@@ -784,8 +787,19 @@ PyGILState_GetThisThreadState(void)
 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