diff options
author | Mark Dickinson <mdickinson@enthought.com> | 2022-06-25 14:11:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-25 14:11:58 (GMT) |
commit | 6b865349aae47b90f9ef0b98f3fe3720c2f05601 (patch) | |
tree | 9896212e12df59b30f9302fdeed61895f0600e3e /Lib/test/test_struct.py | |
parent | 944c7d8a8561d4b637af5c128df1d8d7570ccb46 (diff) | |
download | cpython-6b865349aae47b90f9ef0b98f3fe3720c2f05601.zip cpython-6b865349aae47b90f9ef0b98f3fe3720c2f05601.tar.gz cpython-6b865349aae47b90f9ef0b98f3fe3720c2f05601.tar.bz2 |
gh-94207: Fix struct module leak (GH-94239)
Make _struct.Struct a GC type
This fixes a memory leak in the _struct module, where as soon
as a Struct object is stored in the cache, there's a cycle from
the _struct module to the cache to Struct objects to the Struct
type back to the module. If _struct.Struct is not gc-tracked, that
cycle is never collected.
This PR makes _struct.Struct GC-tracked, and adds a regression test.
Diffstat (limited to 'Lib/test/test_struct.py')
-rw-r--r-- | Lib/test/test_struct.py | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 94873ff..8f14ed3 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -1,10 +1,12 @@ from collections import abc import array +import gc import math import operator import unittest import struct import sys +import weakref from test import support from test.support import import_helper @@ -672,6 +674,21 @@ class StructTest(unittest.TestCase): self.assertIn(b"Exception ignored in:", stderr) self.assertIn(b"C.__del__", stderr) + def test__struct_reference_cycle_cleaned_up(self): + # Regression test for python/cpython#94207. + + # When we create a new struct module, trigger use of its cache, + # and then delete it ... + _struct_module = import_helper.import_fresh_module("_struct") + module_ref = weakref.ref(_struct_module) + _struct_module.calcsize("b") + del _struct_module + + # Then the module should have been garbage collected. + gc.collect() + self.assertIsNone( + module_ref(), "_struct module was not garbage collected") + def test_issue35714(self): # Embedded null characters should not be allowed in format strings. for s in '\0', '2\0i', b'\0': |