The four backend tp_dealloc overrides for torch.cuda.Stream, torch.cuda.Event, torch.xpu.Stream, and torch.xpu.Event silently diverged from their base classes' deallocs (THPStream_dealloc in torch/csrc/Stream.cpp and THPEvent_dealloc in torch/csrc/Event.cpp) when those bases added weakref support in #164304 and #164522.
Since CPython does not chain tp_dealloc automatically for static types, every freed THCPStream / THCPEvent / THXPStream / THXPEvent instance has been leaving:
- dangling weakrefs (no
PyObject_ClearWeakRefs(self)call), and - a leaked lazy stream context in the Stream subclasses (no
Py_CLEAR(self->context)call).
The dangling weakrefs sat latent until #180497 made the dynamo external-object registry populate a weakref.ref(torch.cuda.current_stream()) on every torch.compile invocation referencing current_stream().
From that point on, anything that triggered the dynamo registry plus a finalize-time GC pass would _PyModule_ClearDict walk the registry's now-dangling weakrefs at Py_FinalizeEx and SIGSEGV in clear_weakref → _PyObject_GET_WEAKREFS_LISTPTR → PyType_Check(NULL).
Pull Request resolved: #183403
Approved by: https://github.com/guangyey, https://github.com/ngimel
Co-authored-by: Natalia Gimelshein [email protected]