Skip to content

Commit

Permalink
gh-127314: Don't mention the GIL when calling without a thread state …
Browse files Browse the repository at this point in the history
…on the free-threaded build (#127315)

Co-authored-by: Victor Stinner <[email protected]>
  • Loading branch information
ZeroIntensity and vstinner authored Dec 6, 2024
1 parent a353455 commit 12680ec
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 7 deletions.
8 changes: 8 additions & 0 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,18 @@ static inline void
_Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
{
if (tstate == NULL) {
#ifndef Py_GIL_DISABLED
_Py_FatalErrorFunc(func,
"the function must be called with the GIL held, "
"after Python initialization and before Python finalization, "
"but the GIL is released (the current Python thread state is NULL)");
#else
_Py_FatalErrorFunc(func,
"the function must be called with an active thread state, "
"after Python initialization and before Python finalization, "
"but it was called without an active thread state. "
"Are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?");
#endif
}
}

Expand Down
9 changes: 7 additions & 2 deletions Lib/test/test_capi/test_mem.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ def test_api_misuse(self):

def check_malloc_without_gil(self, code):
out = self.check(code)
expected = ('Fatal Python error: _PyMem_DebugMalloc: '
'Python memory allocator called without holding the GIL')
if not support.Py_GIL_DISABLED:
expected = ('Fatal Python error: _PyMem_DebugMalloc: '
'Python memory allocator called without holding the GIL')
else:
expected = ('Fatal Python error: _PyMem_DebugMalloc: '
'Python memory allocator called without an active thread state. '
'Are you trying to call it inside of a Py_BEGIN_ALLOW_THREADS block?')
self.assertIn(expected, out)

def test_pymem_malloc_without_gil(self):
Expand Down
17 changes: 12 additions & 5 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,18 @@ def test_no_FatalError_infinite_loop(self):
_rc, out, err = run_result
self.assertEqual(out, b'')
# This used to cause an infinite loop.
msg = ("Fatal Python error: PyThreadState_Get: "
"the function must be called with the GIL held, "
"after Python initialization and before Python finalization, "
"but the GIL is released "
"(the current Python thread state is NULL)").encode()
if not support.Py_GIL_DISABLED:
msg = ("Fatal Python error: PyThreadState_Get: "
"the function must be called with the GIL held, "
"after Python initialization and before Python finalization, "
"but the GIL is released "
"(the current Python thread state is NULL)").encode()
else:
msg = ("Fatal Python error: PyThreadState_Get: "
"the function must be called with an active thread state, "
"after Python initialization and before Python finalization, "
"but it was called without an active thread state. "
"Are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?").encode()
self.assertTrue(err.rstrip().startswith(msg),
err)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve error message when calling the C API without an active thread state
on the :term:`free-threaded <free threading>` build.
7 changes: 7 additions & 0 deletions Objects/obmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2910,9 +2910,16 @@ static inline void
_PyMem_DebugCheckGIL(const char *func)
{
if (!PyGILState_Check()) {
#ifndef Py_GIL_DISABLED
_Py_FatalErrorFunc(func,
"Python memory allocator called "
"without holding the GIL");
#else
_Py_FatalErrorFunc(func,
"Python memory allocator called "
"without an active thread state. "
"Are you trying to call it inside of a Py_BEGIN_ALLOW_THREADS block?");
#endif
}
}

Expand Down

0 comments on commit 12680ec

Please sign in to comment.