diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-03-14 21:07:55 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-03-14 21:07:55 (GMT) |
commit | 8a1be61849341528c866924cf69d378ce7790889 (patch) | |
tree | 0b59fbc22edbd703ded539758aae78382d4eec7d /Python | |
parent | 08572f68a980576e883e4eba1227b59782d5192e (diff) | |
download | cpython-8a1be61849341528c866924cf69d378ce7790889.zip cpython-8a1be61849341528c866924cf69d378ce7790889.tar.gz cpython-8a1be61849341528c866924cf69d378ce7790889.tar.bz2 |
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()
Diffstat (limited to 'Python')
-rw-r--r-- | Python/fileutils.c | 16 | ||||
-rw-r--r-- | Python/pylifecycle.c | 5 | ||||
-rw-r--r-- | Python/pystate.c | 24 |
3 files changed, 40 insertions, 5 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c index 06d632a..a710c99 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -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; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index aaf5811..4fc6a15 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -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; diff --git a/Python/pystate.c b/Python/pystate.c index 853e5c7..e8026c5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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 |