GeezerVison is showing github.com — Memory leak on interpreter shutdown when reference cycle exists between `structseq` type and its instance · Issue #157176 · python/cpython
Memory leak on interpreter shutdown when reference cycle exists between structseq type and its instance #157176DescriptionBug report
Bug description:
Environment
- Commit/Branch:
main (rev: 2d9fb5f2f70b18ce9e5d9f7f76fd5ef3f118d838)
- OS: Linux
- Build flags:
CC=clang CXX=clang++ LDFLAGS='-fuse-ld=lld' ./configure --with-address-sanitizer --with-undefined-behavior-sanitizer --with-pydebug && make -j$(nproc)
Steps to reproduce
Run:
./python -c "import time; t = time.gmtime(); type(t).refcyle = t;"
Note: Explicitly breaking the cycle avoids the leak:
./python -c "import time; t = time.gmtime(); type(t).refcyle = t; del type(t).refcyle"
Expected behavior
The garbage collector or interpreter finalization breaks the reference cycle during shutdown; no memory leaks reported by LeakSanitizer.
Actual behavior
LeakSanitizer detects memory leaks (indirect leaks of the type, its dict, descriptors, and the instance):
=================================================================
==1164172==ERROR: LeakSanitizer: detected memory leaks
Indirect leak of 1472 byte(s) in 1 object(s) allocated from:
#0 0x55571ba2f651 in malloc
#1 0x55571c0c8db7 in _PyMem_DebugRawAlloc Objects/obmalloc.c:3103:24
#2 0x55571c130728 in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46:17
#3 0x55571c130728 in _PyType_AllocNoTrack Objects/typeobject.c:2495:19
#4 0x55571c13040d in PyType_GenericAlloc Objects/typeobject.c:2526:21
#5 0x55571c1357f9 in type_from_slots_or_spec Objects/typeobject.c:5591:30
#6 0x55571c1148ec in _PyStructSequence_NewType Objects/structseq.c:780:28
#7 0x55571ca6ea5c in time_exec Modules/timemodule.c:2113:31
...
Indirect leak of 176 byte(s) in 1 object(s) allocated from:
#0 0x55571ba2f651 in malloc
#1 0x55571c0c8db7 in _PyMem_DebugRawAlloc Objects/obmalloc.c:3103:24
#2 0x55571c5d4028 in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46:17
#3 0x55571c5d4028 in gc_alloc Python/gc.c:2013:17
#4 0x55571c5d4440 in _PyObject_GC_NewVar Python/gc.c:2055:25
#5 0x55571c110247 in PyStructSequence_New Objects/structseq.c:77:11
#6 0x55571ca69e1d in tmtotuple Modules/timemodule.c:463:19
#7 0x55571ca67616 in time_gmtime Modules/timemodule.c:541:12
...
SUMMARY: AddressSanitizer: 6946 byte(s) leaked in 50 allocation(s).
Full LeakSanitizer output - logs.txt
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Activitysergey-miryanov commented on Sep 8, 2026 Does this affect 3.14, 3.15 branches? ashm-dev commented on Sep 8, 2026 ContributorAuthor More actions @sergey-miryanov It reproduces on 3.15 and 3.14, but 3.13, 3.12, 3.11, and 3.10 failed with ASan/UBSan errors during the build. methane commented on Sep 15, 2026 How about adding Py_TPFLAGS_IMMUTABLETYPE to struct_time? vstinner commented on Oct 5, 2026
How about adding Py_TPFLAGS_IMMUTABLETYPE to struct_time?
IMO it's perfectly reasonable to make the type immutable. I don't see why someone would want to modify the type.
- state->struct_time_type = PyStructSequence_NewType(&struct_time_type_desc);
+ state->struct_time_type = _PyStructSequence_NewType(&struct_time_type_desc, Py_TPFLAGS_IMMUTABLETYPE);
I tested this change and it works as expected. Reacted by Peter Bierma and Shamil vstinner commented on Oct 7, 2026 type(time.gmtime()) has been made immutable, so it's no longer possible to create circular dependencies:
$ ./python -c "import time; t = time.gmtime(); type(t).refcyle = t;"
Traceback (most recent call last):
File "<string>", line 1, in <module>
import time; t = time.gmtime(); type(t).refcyle = t;
^^^^^^^^^^^^^^^
TypeError: cannot set 'refcyle' attribute of immutable type 'time.struct_time'
I don't think that this issue is important enough to justify a backport. Making a type immutable is a backward incompatible change, so it's only done in Python 3.16 (main branch).
I close the issue.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|