Tags: msgspec/msgspec
Tags
Fix a reference leak of a non-Struct base's type dict (#1199) On Python 3.12+ `MS_GET_TYPE_DICT` expands to `PyType_GetDict`, which returns a new reference; in the comment above the macro the result is described as borrowed. At its only call site, in `structmeta_collect_base`, there is no matching release on either exit, so defining a `Struct` with a non-`Struct` base leaks one reference to that base's type dict. Nothing holds that reference afterwards, so the dict is never freed, and on 3.12 through 3.14 that keeps the base class itself alive along with everything in its namespace, for the rest of the process. `typing.Generic` counts as such a base, so generic `Struct` definitions leak one too, in both the explicit and the PEP 695 spelling; there the dict stays reachable regardless, so only the count grows. Adds a release macro and applies it on both exits. It expands to `Py_XDECREF` on 3.12+ and to nothing before that, where the `tp_dict` slot is read directly and the reference is borrowed. Corrects the comment to match. The remaining `tp_dict` uses in the file are direct slot reads guarded against `NULL` and need no release. A base that has not been readied yet, which a C extension can expose, has no type dict, and on main the `__init__` and `__new__` check crashes on such a base on every supported version. Such a base is now rejected with `TypeError` before its type dict or inherited slots are read, and `TypeError` is also raised if a readied base still has no type dict. The check that the base is a type now comes first. Adds a regression test that the base's contents are released when the base passes the `__init__` and `__new__` check. On current main it fails on 3.12, 3.13 and 3.14, and passes on 3.10 and 3.11, where the leak does not exist. It also passes on main on 3.15, where the leaked dict no longer keeps the base class reachable, so the class is collected and its contents are released even though the dict itself is still retained. Fixes #1198. --------- Co-authored-by: Tseluiko Aleksandr <4410812+Siyet@users.noreply.github.com> Co-authored-by: sobolevn <mail@sobolevn.me>
PreviousNext