Skip to content

[3.12] getattr_static can result in reference leaks#118013

@williamwen42

Description

@williamwen42

Bug report

Bug description:

I discovered this bug while working on pytorch/pytorch#124302.

It looks like calling getattr_static is causing an object to be reference leaked:

importgcfrominspectimportgetattr_staticimportweakrefclassC1: passdefmain(): obj=C1() weakref.finalize(obj, lambda: print("obj deleted!")) classC2: def__init__(self): self.obj=objc2=C2() getattr_static(c2, "bad", None) print("done main!") main() gc.collect() print("done!")

Output:

done main! done! obj deleted! 

If I comment out the getattr_static line, the output is as expected:

done main! obj deleted! done! 

It looks like this PR #104267 indirectly cached calls to getattr_static, which is resulting in reference leaks. Perhaps this cache needs to use weak references?

Original PyTorch code for reference (torch.compile calls getattr_static on mod at some point):

importtorchimportgcimportsysimportweakreffrominspectimportgetattr_staticdefdbg(o): refs=gc.get_referrers(o) print(len(refs), sys.getrefcount(o)) returnrefsgm_list= [] defbackend(gm, _): gm_list.append(weakref.ref(gm, lambda_: print("gm deleted"))) # breakpoint()returngmdefmain(): param=torch.nn.Parameter(torch.randn(5, 5)) classMod(torch.nn.Module): def__init__(self): super().__init__() self.param=paramdefforward(self, x): returnself.param*xmod=Mod() ref=weakref.ref(param, lambda_: print("obj deleted")) opt_mod=torch.compile(mod, backend=backend) print(opt_mod(torch.randn(5, 5))) returnrefref=main() gc.collect() print("done!") print(ref)

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

Labels

3.12only security fixes3.13bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions