Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions 23 Include/internal/pycore_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);
/* Variable and macro for in-line access to current thread
and interpreter state */

/* Similar to _PyThreadState_GET(), but don't check that the GIL is hold. */
static inline PyThreadState* _PyThreadState_GET_UNSAFE(void)
{
return (PyThreadState*)_Py_atomic_load_relaxed(&_PyRuntime.gilstate.tstate_current);
}

/* Get the current Python thread state.

Efficient macro reading directly the 'gilstate.tstate_current' atomic
Expand All @@ -185,8 +191,11 @@ PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);
The caller must hold the GIL.

See also PyThreadState_Get() and PyThreadState_GET(). */
#define _PyThreadState_GET() \
((PyThreadState*)_Py_atomic_load_relaxed(&_PyRuntime.gilstate.tstate_current))
static inline PyThreadState* _PyThreadState_GET(void)
{
assert(PyGILState_Check());
return _PyThreadState_GET_UNSAFE();
}

/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
#undef PyThreadState_GET
Expand All @@ -200,7 +209,15 @@ PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);

See also _PyInterpreterState_Get()
and _PyGILState_GetInterpreterStateUnsafe(). */
#define _PyInterpreterState_GET_UNSAFE() (_PyThreadState_GET()->interp)
static inline PyInterpreterState* _PyInterpreterState_GET_UNSAFE(void)
{
assert(PyGILState_Check());
PyThreadState *tstate = _PyThreadState_GET_UNSAFE();
assert(tstate != NULL);
PyInterpreterState *interp = tstate->interp;
assert(interp != NULL);
return interp;
}


/* Other */
Expand Down
7 changes: 5 additions & 2 deletions 7 Lib/test/test_capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ def test_no_FatalError_infinite_loop(self):
(out, err) = p.communicate()
self.assertEqual(out, b'')
# This used to cause an infinite loop.
self.assertTrue(err.rstrip().startswith(
err = err.rstrip()
cond = err.startswith(
b'Fatal Python error:'
b' PyThreadState_Get: no current thread'))
b' PyThreadState_Get: no current thread')
cond |= bool(re.search(b"Assertion.*PyGILState_Check.*failed", err))
self.assertTrue(cond, err.decode(errors="replace"))

def test_memoryview_from_NULL_pointer(self):
self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer)
Expand Down
3 changes: 2 additions & 1 deletion 3 Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ PyEval_ReleaseLock(void)
We therefore avoid PyThreadState_Get() which dumps a fatal error
in debug mode.
*/
drop_gil(_PyThreadState_GET());
PyThreadState *tstate = _PyThreadState_GET_UNSAFE();
drop_gil(tstate);
}

void
Expand Down
2 changes: 1 addition & 1 deletion 2 Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1916,7 +1916,7 @@ fatal_error(const char *prefix, const char *msg, int status)
and holds the GIL */
PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
if (tss_tstate != NULL) {
PyThreadState *tstate = _PyThreadState_GET();
PyThreadState *tstate = _PyThreadState_GET_UNSAFE();
if (tss_tstate != tstate) {
/* The Python thread does not hold the GIL */
tss_tstate = NULL;
Expand Down
12 changes: 7 additions & 5 deletions 12 Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
PyThreadState *tstate = _PyThreadState_GET();
PyThreadState *tstate = _PyThreadState_GET_UNSAFE();
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
Expand Down Expand Up @@ -776,7 +776,7 @@ PyThreadState_Get(void)
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = _PyThreadState_GET();
PyThreadState *oldts = _PyThreadState_GET_UNSAFE();

_PyThreadState_SET(newts);
/* It should not be possible for more than one thread state
Expand Down Expand Up @@ -957,8 +957,10 @@ static int
PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
return tstate == _PyThreadState_GET();
assert(PyGILState_GetThisThreadState() == tstate);

PyThreadState *current = _PyThreadState_GET_UNSAFE();
return (tstate == current);
}

/* Internal initialization/finalization functions called by
Expand Down Expand Up @@ -1085,7 +1087,7 @@ PyGILState_Check(void)
return 1;
}

tstate = _PyThreadState_GET();
tstate = _PyThreadState_GET_UNSAFE();
if (tstate == NULL)
return 0;

Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.