Skip to content

Commit 37dbbb2

Browse files
gh-99578: Fix refleak in _imp.create_builtin() (GH-99642)
Fix a reference bug in _imp.create_builtin() after the creation of the first sub-interpreter for modules "builtins" and "sys". (cherry picked from commit cb2ef8b) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 101dfae commit 37dbbb2

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

Lib/test/test_imp.py

+30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import gc
12
import importlib
23
import importlib.util
34
import os
@@ -379,6 +380,35 @@ def test_find_and_load_checked_pyc(self):
379380
self.assertEqual(mod.x, 42)
380381

381382

383+
@support.cpython_only
384+
def test_create_builtin_subinterp(self):
385+
# gh-99578: create_builtin() behavior changes after the creation of the
386+
# first sub-interpreter. Test both code paths, before and after the
387+
# creation of a sub-interpreter. Previously, create_builtin() had
388+
# a reference leak after the creation of the first sub-interpreter.
389+
390+
import builtins
391+
create_builtin = support.get_attribute(_imp, "create_builtin")
392+
class Spec:
393+
name = "builtins"
394+
spec = Spec()
395+
396+
def check_get_builtins():
397+
refcnt = sys.getrefcount(builtins)
398+
mod = _imp.create_builtin(spec)
399+
self.assertIs(mod, builtins)
400+
self.assertEqual(sys.getrefcount(builtins), refcnt + 1)
401+
# Check that a GC collection doesn't crash
402+
gc.collect()
403+
404+
check_get_builtins()
405+
406+
ret = support.run_in_subinterp("import builtins")
407+
self.assertEqual(ret, 0)
408+
409+
check_get_builtins()
410+
411+
382412
class ReloadTests(unittest.TestCase):
383413

384414
"""Very basic tests to make sure that imp.reload() operates just like
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a reference bug in :func:`_imp.create_builtin()` after the creation of the
2+
first sub-interpreter for modules ``builtins`` and ``sys``. Patch by Victor
3+
Stinner.

Python/import.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,8 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
10061006
if (_PyUnicode_EqualToASCIIString(name, p->name)) {
10071007
if (p->initfunc == NULL) {
10081008
/* Cannot re-init internal module ("sys" or "builtins") */
1009-
return PyImport_AddModuleObject(name);
1009+
mod = PyImport_AddModuleObject(name);
1010+
return Py_XNewRef(mod);
10101011
}
10111012

10121013
mod = (*p->initfunc)();

0 commit comments

Comments
 (0)