https://github.com/python/cpython/commit/12680ec5bd45c85b6daebe0739d30ef45f089efa
commit: 12680ec5bd45c85b6daebe0739d30ef45f089efa
branch: main
author: Peter Bierma <[email protected]>
committer: vstinner <[email protected]>
date: 2024-12-06T16:58:19+01:00
summary:

gh-127314: Don't mention the GIL when calling without a thread state on the 
free-threaded build (#127315)

Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst
M Include/internal/pycore_pystate.h
M Lib/test/test_capi/test_mem.py
M Lib/test/test_capi/test_misc.py
M Objects/obmalloc.c

diff --git a/Include/internal/pycore_pystate.h 
b/Include/internal/pycore_pystate.h
index 54d8803bc0bdb6..1e73e541ef8de0 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -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
     }
 }
 
diff --git a/Lib/test/test_capi/test_mem.py b/Lib/test/test_capi/test_mem.py
index 6ab7b685c2e18b..5035b2b4829bf6 100644
--- a/Lib/test/test_capi/test_mem.py
+++ b/Lib/test/test_capi/test_mem.py
@@ -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):
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 8e0271919cc8a5..61512e610f46f2 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -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)
 
diff --git 
a/Misc/NEWS.d/next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst 
b/Misc/NEWS.d/next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst
new file mode 100644
index 00000000000000..8ea3c4ee2a2c53
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst
@@ -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.
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 2cc0377f68f990..b103deb01ca712 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -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
     }
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to