Kaydet (Commit) 8a1be618 authored tarafından Victor Stinner's avatar Victor Stinner

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()
üst 08572f68
...@@ -247,6 +247,10 @@ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); ...@@ -247,6 +247,10 @@ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void);
* currently holds the GIL, 0 otherwise * currently holds the GIL, 0 otherwise
*/ */
#ifndef Py_LIMITED_API #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); PyAPI_FUNC(int) PyGILState_Check(void);
#endif #endif
......
...@@ -37,6 +37,14 @@ Py_Exit(int sts) ...@@ -37,6 +37,14 @@ Py_Exit(int sts)
exit(sts); exit(sts);
} }
#ifdef WITH_THREAD
/* Needed by obmalloc.c */
int PyGILState_Check(void)
{
return 1;
}
#endif
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
......
...@@ -683,6 +683,10 @@ _Py_fstat(int fd, struct _Py_stat_struct *status) ...@@ -683,6 +683,10 @@ _Py_fstat(int fd, struct _Py_stat_struct *status)
{ {
int res; int res;
#ifdef WITH_THREAD
assert(PyGILState_Check());
#endif
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
res = _Py_fstat_noraise(fd, status); res = _Py_fstat_noraise(fd, status);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
...@@ -1164,6 +1168,10 @@ _Py_read(int fd, void *buf, size_t count) ...@@ -1164,6 +1168,10 @@ _Py_read(int fd, void *buf, size_t count)
int err; int err;
int async_err = 0; int async_err = 0;
#ifdef WITH_THREAD
assert(PyGILState_Check());
#endif
/* _Py_read() must not be called with an exception set, otherwise the /* _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 * caller may think that read() was interrupted by a signal and the signal
* handler raised an exception. */ * handler raised an exception. */
...@@ -1319,6 +1327,10 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held) ...@@ -1319,6 +1327,10 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
Py_ssize_t Py_ssize_t
_Py_write(int fd, const void *buf, size_t count) _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 /* _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 * caller may think that write() was interrupted by a signal and the signal
* handler raised an exception. */ * handler raised an exception. */
...@@ -1468,6 +1480,10 @@ _Py_dup(int fd) ...@@ -1468,6 +1480,10 @@ _Py_dup(int fd)
DWORD ftype; DWORD ftype;
#endif #endif
#ifdef WITH_THREAD
assert(PyGILState_Check());
#endif
if (!_PyVerify_fd(fd)) { if (!_PyVerify_fd(fd)) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return -1; return -1;
......
...@@ -692,6 +692,7 @@ Py_FinalizeEx(void) ...@@ -692,6 +692,7 @@ Py_FinalizeEx(void)
/* Delete current thread. After this, many C API calls become crashy. */ /* Delete current thread. After this, many C API calls become crashy. */
PyThreadState_Swap(NULL); PyThreadState_Swap(NULL);
PyInterpreterState_Delete(interp); PyInterpreterState_Delete(interp);
#ifdef Py_TRACE_REFS #ifdef Py_TRACE_REFS
...@@ -743,6 +744,10 @@ Py_NewInterpreter(void) ...@@ -743,6 +744,10 @@ Py_NewInterpreter(void)
if (!initialized) if (!initialized)
Py_FatalError("Py_NewInterpreter: call Py_Initialize first"); 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(); interp = PyInterpreterState_New();
if (interp == NULL) if (interp == NULL)
return NULL; return NULL;
......
...@@ -34,6 +34,8 @@ to avoid the expense of doing their own locking). ...@@ -34,6 +34,8 @@ to avoid the expense of doing their own locking).
extern "C" { extern "C" {
#endif #endif
int _PyGILState_check_enabled = 1;
#ifdef WITH_THREAD #ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ 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 */ ...@@ -45,7 +47,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
GILState implementation GILState implementation
*/ */
static PyInterpreterState *autoInterpreterState = NULL; static PyInterpreterState *autoInterpreterState = NULL;
static int autoTLSkey = 0; static int autoTLSkey = -1;
#else #else
#define HEAD_INIT() /* Nothing */ #define HEAD_INIT() /* Nothing */
#define HEAD_LOCK() /* Nothing */ #define HEAD_LOCK() /* Nothing */
...@@ -449,10 +451,10 @@ PyThreadState_DeleteCurrent() ...@@ -449,10 +451,10 @@ PyThreadState_DeleteCurrent()
if (tstate == NULL) if (tstate == NULL)
Py_FatalError( Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate"); "PyThreadState_DeleteCurrent: no current tstate");
SET_TSTATE(NULL); tstate_delete_common(tstate);
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey); PyThread_delete_key_value(autoTLSkey);
tstate_delete_common(tstate); SET_TSTATE(NULL);
PyEval_ReleaseLock(); PyEval_ReleaseLock();
} }
#endif /* WITH_THREAD */ #endif /* WITH_THREAD */
...@@ -716,6 +718,7 @@ void ...@@ -716,6 +718,7 @@ void
_PyGILState_Fini(void) _PyGILState_Fini(void)
{ {
PyThread_delete_key(autoTLSkey); PyThread_delete_key(autoTLSkey);
autoTLSkey = -1;
autoInterpreterState = NULL; autoInterpreterState = NULL;
} }
...@@ -784,8 +787,19 @@ PyGILState_GetThisThreadState(void) ...@@ -784,8 +787,19 @@ PyGILState_GetThisThreadState(void)
int int
PyGILState_Check(void) PyGILState_Check(void)
{ {
PyThreadState *tstate = GET_TSTATE(); PyThreadState *tstate;
return tstate && (tstate == PyGILState_GetThisThreadState());
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 PyGILState_STATE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment