summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_struct.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-06-25 14:40:14 (GMT)
committerGitHub <noreply@github.com>2022-06-25 14:40:14 (GMT)
commit4bc5f9fe8cd44010c9919207cefdcb3e08606044 (patch)
tree159d234c4c8c7c1f7fe00b771f8661aad474e96a /Lib/test/test_struct.py
parent89ba660717a890359c2f50e74a711daf037ef70d (diff)
downloadcpython-4bc5f9fe8cd44010c9919207cefdcb3e08606044.zip
cpython-4bc5f9fe8cd44010c9919207cefdcb3e08606044.tar.gz
cpython-4bc5f9fe8cd44010c9919207cefdcb3e08606044.tar.bz2
gh-94207: Fix struct module leak (GH-94239) (GH-94265)
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. (cherry picked from commit 6b865349aae47b90f9ef0b98f3fe3720c2f05601) Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
Diffstat (limited to 'Lib/test/test_struct.py')
-rw-r--r--Lib/test/test_struct.py17
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':