Skip to content

[3.12] getattr_static can result in reference leaks #118013

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