summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_symtable.h2
-rw-r--r--Lib/test/test_cmd_line.py5
-rw-r--r--Python/pylifecycle.c4
-rw-r--r--Python/symtable.c17
4 files changed, 25 insertions, 3 deletions
diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h
index 28935f4..4ecfab5 100644
--- a/Include/internal/pycore_symtable.h
+++ b/Include/internal/pycore_symtable.h
@@ -128,6 +128,8 @@ extern struct symtable* _Py_SymtableStringObjectFlags(
int start,
PyCompilerFlags *flags);
+extern void _PySymtable_Fini(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 86ee274..fa5f39e 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -119,7 +119,10 @@ class CmdLineTest(unittest.TestCase):
rc, out, err = run_python('-X', 'showrefcount', '-c', code)
self.assertEqual(out.rstrip(), b"{'showrefcount': True}")
if Py_DEBUG:
- self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]')
+ # bpo-46417: Tolerate negative reference count which can occur
+ # because of bugs in C extensions. This test is only about checking
+ # the showrefcount feature.
+ self.assertRegex(err, br'^\[-?\d+ refs, \d+ blocks\]')
else:
self.assertEqual(err, b'')
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 92c8ad0..9d10f94 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -23,6 +23,7 @@
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
#include "pycore_sliceobject.h" // _PySlice_Fini()
#include "pycore_structseq.h" // _PyStructSequence_InitState()
+#include "pycore_symtable.h" // _PySymtable_Fini()
#include "pycore_sysmodule.h" // _PySys_ClearAuditHooks()
#include "pycore_traceback.h" // _Py_DumpTracebackThreads()
#include "pycore_tuple.h" // _PyTuple_InitTypes()
@@ -1700,6 +1701,9 @@ finalize_interp_clear(PyThreadState *tstate)
int is_main_interp = _Py_IsMainInterpreter(tstate->interp);
_PyExc_ClearExceptionGroupType(tstate->interp);
+ if (is_main_interp) {
+ _PySymtable_Fini();
+ }
/* Clear interpreter state and all thread states */
_PyInterpreterState_Clear(tstate);
diff --git a/Python/symtable.c b/Python/symtable.c
index 01c6ec1..e9bdff3 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1121,7 +1121,7 @@ static int
symtable_add_def(struct symtable *st, PyObject *name, int flag,
int lineno, int col_offset, int end_lineno, int end_col_offset)
{
- return symtable_add_def_helper(st, name, flag, st->st_cur,
+ return symtable_add_def_helper(st, name, flag, st->st_cur,
lineno, col_offset, end_lineno, end_col_offset);
}
@@ -2134,7 +2134,7 @@ symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_t
static int
symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) {
_Py_comprehension_ty type = st->st_cur->ste_comprehension;
- PyErr_SetString(PyExc_SyntaxError,
+ PyErr_SetString(PyExc_SyntaxError,
(type == ListComprehension) ? "'yield' inside list comprehension" :
(type == SetComprehension) ? "'yield' inside set comprehension" :
(type == DictComprehension) ? "'yield' inside dict comprehension" :
@@ -2173,3 +2173,16 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
_PyArena_Free(arena);
return st;
}
+
+void
+_PySymtable_Fini(void)
+{
+ Py_CLEAR(top);
+ Py_CLEAR(lambda);
+ Py_CLEAR(genexpr);
+ Py_CLEAR(listcomp);
+ Py_CLEAR(setcomp);
+ Py_CLEAR(dictcomp);
+ Py_CLEAR(__class__);
+ Py_CLEAR(_annotation);
+}