_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
}
}
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):
_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)
--- /dev/null
+Improve error message when calling the C API without an active thread state
+on the :term:`free-threaded <free threading>` build.
_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
}
}