[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