From 63b97720c6c1ec08b39aa9738300cf5aebc628b4 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 26 Nov 2024 22:03:41 -0500 Subject: [PATCH 01/13] Improve error message for a NULL tstate on the free-threaded build. --- Include/internal/pycore_pystate.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 54d8803bc0bdb6..9ee75f2a5c9314 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -190,10 +190,17 @@ 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 is NULL " + "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)"); +#endif } } From de0e446c07a324d4bdd85676a6586c2d8ec22e30 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 26 Nov 2024 22:06:15 -0500 Subject: [PATCH 02/13] Add blurb --- .../next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/C_API/2024-11-26-22-06-10.gh-issue-127314.SsRrIu.rst 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 ` build. From 2f53c947213ceda58f88ad042bae915bfcd4ae0f Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 26 Nov 2024 22:14:40 -0500 Subject: [PATCH 03/13] Update the tests. --- Lib/test/test_capi/test_misc.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 80e705a37c4c5e..9eb8740562b370 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -100,11 +100,17 @@ 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 is NULL " + "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)").encode() self.assertTrue(err.rstrip().startswith(msg), err) From 55ffc32e2b50e858249180ce2bc29173785318ce Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 26 Nov 2024 22:19:17 -0500 Subject: [PATCH 04/13] Improve obmalloc error message. --- Objects/obmalloc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 2cc0377f68f990..45cd43c2a2d301 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 } } From 571e16f4e77b23eea2624d345418482acbe00d66 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 26 Nov 2024 22:21:51 -0500 Subject: [PATCH 05/13] Fix C API memory tests. --- Lib/test/test_capi/test_mem.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_capi/test_mem.py b/Lib/test/test_capi/test_mem.py index 6ab7b685c2e18b..3c69fb0f68e87c 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): From b2c0dfcdda183ec020cc5ae06d4a215e790c2e73 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Dec 2024 11:20:48 -0500 Subject: [PATCH 06/13] Update obmalloc.c Co-authored-by: Victor Stinner --- Objects/obmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 45cd43c2a2d301..b103deb01ca712 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -2918,7 +2918,7 @@ _PyMem_DebugCheckGIL(const char *func) _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?)"); + "Are you trying to call it inside of a Py_BEGIN_ALLOW_THREADS block?"); #endif } } From 2d6925911cde76e7545f4fa12d899241ac0f3180 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Dec 2024 11:22:17 -0500 Subject: [PATCH 07/13] =?UTF-8?q?Clarify=20=E2=80=9Cit=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Include/internal/pycore_pystate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 9ee75f2a5c9314..73e228f6babdb8 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -198,7 +198,7 @@ _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate) #else _Py_FatalErrorFunc(func, "the function must be called with an active thread state, " - "after Python initialization and before Python finalization, but it is NULL " + "after Python initialization and before Python finalization, but the thread state is NULL. " "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)"); #endif } From bcdf15777f5b0d28521751a8325fbbcd8c03f7dc Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Dec 2024 11:25:23 -0500 Subject: [PATCH 08/13] Fix the test --- Lib/test/test_capi/test_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 9eb8740562b370..1f4417379cf3f5 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -109,7 +109,7 @@ def test_no_FatalError_infinite_loop(self): 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 is NULL " + "after Python initialization and before Python finalization, but the thread state is NULL " "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)").encode() self.assertTrue(err.rstrip().startswith(msg), err) From d59d134058bd95cb34ad6c314d6a647e353f7b92 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Dec 2024 11:27:12 -0500 Subject: [PATCH 09/13] Remove parens in test --- Lib/test/test_capi/test_mem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_mem.py b/Lib/test/test_capi/test_mem.py index 3c69fb0f68e87c..5035b2b4829bf6 100644 --- a/Lib/test/test_capi/test_mem.py +++ b/Lib/test/test_capi/test_mem.py @@ -74,7 +74,7 @@ def check_malloc_without_gil(self, code): 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?)') + '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): From 55fafedeb8525e47c2333d10357d8eb09aed005e Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Dec 2024 11:29:06 -0500 Subject: [PATCH 10/13] Add missing period --- Lib/test/test_capi/test_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 1f4417379cf3f5..7d82400daa3335 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -109,7 +109,7 @@ def test_no_FatalError_infinite_loop(self): 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 the thread state is NULL " + "after Python initialization and before Python finalization, but the thread state is NULL. " "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)").encode() self.assertTrue(err.rstrip().startswith(msg), err) From 910a204537c761740f96fb39d9a73fa0fdc1e543 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 3 Dec 2024 07:24:23 -0500 Subject: [PATCH 11/13] Update pycore_pystate.h Co-authored-by: Victor Stinner --- Include/internal/pycore_pystate.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 73e228f6babdb8..1e73e541ef8de0 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -198,8 +198,9 @@ _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate) #else _Py_FatalErrorFunc(func, "the function must be called with an active thread state, " - "after Python initialization and before Python finalization, but the thread state is NULL. " - "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)"); + "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 } } From 4999bbf55a64ce1e49183e52a2112845f5b8550b Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 3 Dec 2024 07:26:51 -0500 Subject: [PATCH 12/13] Match the test --- Lib/test/test_capi/test_misc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 7d82400daa3335..f6b3a38cb054ef 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -107,10 +107,10 @@ def test_no_FatalError_infinite_loop(self): "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 the thread state is NULL. " - "(are you trying to call the C API inside of a Py_BEGIN_ALLOW_THREADS block?)").encode() + msg = ("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) From 3bb19a5cff659f69ac6f18cdd5d3e4b3ff2dee29 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 3 Dec 2024 07:28:24 -0500 Subject: [PATCH 13/13] Add missing prefix --- Lib/test/test_capi/test_misc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index f6b3a38cb054ef..81df5d23e26048 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -107,7 +107,8 @@ def test_no_FatalError_infinite_loop(self): "but the GIL is released " "(the current Python thread state is NULL)").encode() else: - msg = ("the function must be called with an active thread state, " + 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()