Skip to content

Commit 12f4ac3

Browse files
authored
bpo-46417: Clear symtable identifiers at exit (GH-30809)
Add _PySymtable_Fini() function, called by finalize_interp_clear(). Update test_cmd_line.test_showrefcount() to tolerate negative reference count.
1 parent 1ded8ed commit 12f4ac3

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

Include/internal/pycore_symtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ extern struct symtable* _Py_SymtableStringObjectFlags(
128128
int start,
129129
PyCompilerFlags *flags);
130130

131+
extern void _PySymtable_Fini(void);
132+
131133
#ifdef __cplusplus
132134
}
133135
#endif

Lib/test/test_cmd_line.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ def run_python(*args):
119119
rc, out, err = run_python('-X', 'showrefcount', '-c', code)
120120
self.assertEqual(out.rstrip(), b"{'showrefcount': True}")
121121
if Py_DEBUG:
122-
self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]')
122+
# bpo-46417: Tolerate negative reference count which can occur
123+
# because of bugs in C extensions. This test is only about checking
124+
# the showrefcount feature.
125+
self.assertRegex(err, br'^\[-?\d+ refs, \d+ blocks\]')
123126
else:
124127
self.assertEqual(err, b'')
125128

Python/pylifecycle.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
2424
#include "pycore_sliceobject.h" // _PySlice_Fini()
2525
#include "pycore_structseq.h" // _PyStructSequence_InitState()
26+
#include "pycore_symtable.h" // _PySymtable_Fini()
2627
#include "pycore_sysmodule.h" // _PySys_ClearAuditHooks()
2728
#include "pycore_traceback.h" // _Py_DumpTracebackThreads()
2829
#include "pycore_tuple.h" // _PyTuple_InitTypes()
@@ -1700,6 +1701,9 @@ finalize_interp_clear(PyThreadState *tstate)
17001701
int is_main_interp = _Py_IsMainInterpreter(tstate->interp);
17011702

17021703
_PyExc_ClearExceptionGroupType(tstate->interp);
1704+
if (is_main_interp) {
1705+
_PySymtable_Fini();
1706+
}
17031707

17041708
/* Clear interpreter state and all thread states */
17051709
_PyInterpreterState_Clear(tstate);

Python/symtable.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ static int
11211121
symtable_add_def(struct symtable *st, PyObject *name, int flag,
11221122
int lineno, int col_offset, int end_lineno, int end_col_offset)
11231123
{
1124-
return symtable_add_def_helper(st, name, flag, st->st_cur,
1124+
return symtable_add_def_helper(st, name, flag, st->st_cur,
11251125
lineno, col_offset, end_lineno, end_col_offset);
11261126
}
11271127

@@ -2134,7 +2134,7 @@ symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_t
21342134
static int
21352135
symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) {
21362136
_Py_comprehension_ty type = st->st_cur->ste_comprehension;
2137-
PyErr_SetString(PyExc_SyntaxError,
2137+
PyErr_SetString(PyExc_SyntaxError,
21382138
(type == ListComprehension) ? "'yield' inside list comprehension" :
21392139
(type == SetComprehension) ? "'yield' inside set comprehension" :
21402140
(type == DictComprehension) ? "'yield' inside dict comprehension" :
@@ -2173,3 +2173,16 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
21732173
_PyArena_Free(arena);
21742174
return st;
21752175
}
2176+
2177+
void
2178+
_PySymtable_Fini(void)
2179+
{
2180+
Py_CLEAR(top);
2181+
Py_CLEAR(lambda);
2182+
Py_CLEAR(genexpr);
2183+
Py_CLEAR(listcomp);
2184+
Py_CLEAR(setcomp);
2185+
Py_CLEAR(dictcomp);
2186+
Py_CLEAR(__class__);
2187+
Py_CLEAR(_annotation);
2188+
}

0 commit comments

Comments
 (0)