bpo-38733: PyErr_Occurred() caller must hold the GIL (GH-17080)

bpo-3605, bpo-38733: Optimize _PyErr_Occurred(): remove "tstate ==
NULL" test.

Py_FatalError() no longer calls PyErr_Occurred() if called without
holding the GIL. So PyErr_Occurred() no longer has to support
tstate==NULL case.

_Py_CheckFunctionResult(): use directly _PyErr_Occurred() to avoid
explicit "!= NULL" test.
This commit is contained in:
Victor Stinner 2019-11-07 12:42:07 +01:00 committed by GitHub
parent 991b02dc87
commit d12d0e7c0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 12 additions and 7 deletions

View File

@ -374,6 +374,8 @@ Querying the error indicator
own a reference to the return value, so you do not need to :c:func:`Py_DECREF` own a reference to the return value, so you do not need to :c:func:`Py_DECREF`
it. it.
The caller must hold the GIL.
.. note:: .. note::
Do not compare the return value to a specific exception; use Do not compare the return value to a specific exception; use

View File

@ -10,7 +10,8 @@ extern "C" {
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
{ {
return tstate == NULL ? NULL : tstate->curexc_type; assert(tstate != NULL);
return tstate->curexc_type;
} }

View File

@ -30,12 +30,10 @@ PyObject*
_Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable, _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
PyObject *result, const char *where) PyObject *result, const char *where)
{ {
int err_occurred = (_PyErr_Occurred(tstate) != NULL);
assert((callable != NULL) ^ (where != NULL)); assert((callable != NULL) ^ (where != NULL));
if (result == NULL) { if (result == NULL) {
if (!err_occurred) { if (!_PyErr_Occurred(tstate)) {
if (callable) if (callable)
_PyErr_Format(tstate, PyExc_SystemError, _PyErr_Format(tstate, PyExc_SystemError,
"%R returned NULL without setting an error", "%R returned NULL without setting an error",
@ -52,7 +50,7 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
} }
} }
else { else {
if (err_occurred) { if (_PyErr_Occurred(tstate)) {
Py_DECREF(result); Py_DECREF(result);
if (callable) { if (callable) {

View File

@ -2313,12 +2313,13 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
return data; return data;
} }
static void static inline void
_PyMem_DebugCheckGIL(void) _PyMem_DebugCheckGIL(void)
{ {
if (!PyGILState_Check()) if (!PyGILState_Check()) {
Py_FatalError("Python memory allocator called " Py_FatalError("Python memory allocator called "
"without holding the GIL"); "without holding the GIL");
}
} }
static void * static void *

View File

@ -218,6 +218,9 @@ PyErr_SetString(PyObject *exception, const char *string)
PyObject* _Py_HOT_FUNCTION PyObject* _Py_HOT_FUNCTION
PyErr_Occurred(void) PyErr_Occurred(void)
{ {
/* The caller must hold the GIL. */
assert(PyGILState_Check());
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
return _PyErr_Occurred(tstate); return _PyErr_Occurred(tstate);
} }