From 02918aa96117781261cb1a564e37a861b01eb883 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Tue, 12 Mar 2024 12:00:49 +0000 Subject: [PATCH] gh-116604: Correctly honor the gc status when calling _Py_RunGC (#116628) --- Lib/test/test_gc.py | 25 +++++++++++++++++++ ...-03-11-22-24-59.gh-issue-116604.LCEzAT.rst | 3 +++ Python/gc.c | 4 +++ 3 files changed, 32 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-03-11-22-24-59.gh-issue-116604.LCEzAT.rst diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index dd09643788d..2aea025fcc1 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1397,6 +1397,31 @@ class GCTogglingTests(unittest.TestCase): # empty __dict__. self.assertEqual(x, None) + def test_indirect_calls_with_gc_disabled(self): + junk = [] + i = 0 + detector = GC_Detector() + while not detector.gc_happened: + i += 1 + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") + junk.append([]) # this will eventually trigger gc + + try: + gc.disable() + junk = [] + i = 0 + detector = GC_Detector() + while not detector.gc_happened: + i += 1 + if i > 10000: + break + junk.append([]) # this may eventually trigger gc (if it is enabled) + + self.assertEqual(i, 10001) + finally: + gc.enable() + class PythonFinalizationTests(unittest.TestCase): def test_ast_fini(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-11-22-24-59.gh-issue-116604.LCEzAT.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-11-22-24-59.gh-issue-116604.LCEzAT.rst new file mode 100644 index 00000000000..516edfa9e6c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-11-22-24-59.gh-issue-116604.LCEzAT.rst @@ -0,0 +1,3 @@ +Respect the status of the garbage collector when indirect calls are made via +:c:func:`PyErr_CheckSignals` and the evaluation breaker. Patch by Pablo +Galindo diff --git a/Python/gc.c b/Python/gc.c index ea3b596d171..6b3316b642e 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -1805,6 +1805,10 @@ _PyObject_GC_Link(PyObject *op) void _Py_RunGC(PyThreadState *tstate) { + GCState *gcstate = get_gc_state(); + if (!gcstate->enabled) { + return; + } gc_collect_main(tstate, GENERATION_AUTO, _Py_GC_REASON_HEAP); }