From: Mark Shannon Date: Tue, 23 Dec 2025 17:19:34 +0000 (+0000) Subject: GH-143026: Fix assertion error in executor management. (GH-143104) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20aeb3a4631beebd255781ba4932b53011edb011;p=thirdparty%2FPython%2Fcpython.git GH-143026: Fix assertion error in executor management. (GH-143104) --- diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 6b91e4334b16..d14cee6af661 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -252,25 +252,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) } } -static inline void -_Py_DECREF_NO_DEALLOC(PyObject *op) -{ - if (_Py_IsImmortal(op)) { - _Py_DECREF_IMMORTAL_STAT_INC(); - return; - } - _Py_DECREF_STAT_INC(); -#ifdef Py_REF_DEBUG - _Py_DEC_REFTOTAL(PyInterpreterState_Get()); -#endif - op->ob_refcnt--; -#ifdef Py_DEBUG - if (op->ob_refcnt <= 0) { - _Py_FatalRefcountError("Expected a positive remaining refcount"); - } -#endif -} - #else // TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build static inline void @@ -279,12 +260,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) Py_DECREF(op); } -static inline void -_Py_DECREF_NO_DEALLOC(PyObject *op) -{ - Py_DECREF(op); -} - static inline int _Py_REF_IS_MERGED(Py_ssize_t ob_ref_shared) { diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 3ee62f172832..6a0fc1a59e79 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -27,6 +27,7 @@ typedef struct { uint8_t valid; uint8_t chain_depth; // Must be big enough for MAX_CHAIN_DEPTH - 1. bool warm; + uint8_t pending_deletion; int32_t index; // Index of ENTER_EXECUTOR (if code isn't NULL, below). _PyBloomFilter bloom; _PyExecutorLinkListNode links; diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 3d2b61d355a3..16288a447e20 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3114,6 +3114,26 @@ class TestUopsOptimization(unittest.TestCase): self.assertNotIn("_POP_TOP_INT", uops) self.assertIn("_POP_TOP_NOP", uops) + def test_143026(self): + # https://github.com/python/cpython/issues/143026 + + result = script_helper.run_python_until_end('-c', textwrap.dedent(""" + import gc + thresholds = gc.get_threshold() + try: + gc.set_threshold(1) + + def f1(): + for i in range(5000): + globals()[''] = i + + f1() + finally: + gc.set_threshold(*thresholds) + """), PYTHON_JIT="1") + self.assertEqual(result[0].rc, 0, result) + + def global_identity(x): return x diff --git a/Python/optimizer.c b/Python/optimizer.c index 869889bf2598..0f8ddb4ba558 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -310,7 +310,7 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp) while (ts) { _PyExecutorObject *current = (_PyExecutorObject *)ts->current_executor; if (current != NULL) { - _Py_DECREF_NO_DEALLOC((PyObject *)current); + Py_DECREF((PyObject *)current); } ts = ts->next; } @@ -320,6 +320,10 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp) static void add_to_pending_deletion_list(_PyExecutorObject *self) { + if (self->vm_data.pending_deletion) { + return; + } + self->vm_data.pending_deletion = 1; PyInterpreterState *interp = PyInterpreterState_Get(); self->vm_data.links.previous = NULL; self->vm_data.links.next = interp->executor_deletion_list_head; @@ -627,7 +631,7 @@ _PyJit_translate_single_bytecode_to_trace( uint32_t target = 0; target = Py_IsNone((PyObject *)old_code) - ? (int)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR) + ? (uint32_t)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR) : INSTR_IP(target_instr, old_code); // Rewind EXTENDED_ARG so that we see the whole thing. @@ -1666,6 +1670,7 @@ void _Py_ExecutorInit(_PyExecutorObject *executor, const _PyBloomFilter *dependency_set) { executor->vm_data.valid = true; + executor->vm_data.pending_deletion = 0; for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) { executor->vm_data.bloom.bits[i] = dependency_set->bits[i]; } diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 659befe312af..2001fb7c3793 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -673,7 +673,6 @@ NON_ESCAPING_FUNCTIONS = ( "_PyUnicode_Equal", "_PyUnicode_JoinArray", "_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY", - "_Py_DECREF_NO_DEALLOC", "_Py_ID", "_Py_IsImmortal", "_Py_IsOwnedByCurrentThread",