Finalizers make debugging difficult

I’ve spent the past 2 days trying to answer a basic question: Why is a certain method on one of my classes being called? The PDB stack trace looked completely spurious, because it showed the method getting called out of nowhere. It appeared that literally any function, even built-in functions, could suddenly call the method on my class, with any instance of that class. So I assumed that the PDB stack trace was spurious.

I filled my code with debug logs, but they suggested the same thing. “Maybe logging is broken”, I speculated.

Finally, I took the overkill option: I tried debugging the CPython process with GDB. Nothing is directly visible from there. The commands in Python’s Misc/gdbinit script that are supposed to show the Python stack froze instead. So I asked ChatGPT how to debug it, which wasn’t easy because ChatGPT would rather shotgun-debug than do any actual debugging. But once I convinced it to focus on GDB, it helped me see that the C stack looked just as weird as the stack that PDB showed, except you could see that the C function finalize_garbage() was running, higher on the call stack than some functions ChatGPT helped me determine were part of my program. So the mystery was solved.

My request: Make it possible to see the finalizer from PDB. If I knew my function was being called from the garbage collector, it would’ve saved me a lot of time.

Why would the finalizer call a method on the object? Did you define a __del__() method?

def __del__(self):
1 Like

Thanks for the detailed explanation. That certainly sounds like a pain point, and what you’re looking for sounds reasonable (though further analysis might be warranted and there might be other options).

Your best course of action right now is to open a new issue, pretty much copying what you already wrote.

I can’t comment on other debug capabilities, but I believe GDB’s native Python debugging capabilities have improved dramatically since I first wrote the gdbinit user commands. I suspect they are probably not useful anymore and should either be removed from the cpython repo or more heavily commented to encourage people to try GDB’s more recent Python support first.

Could you share an example? I have the same question - why was your method being called during garbage collection. If it’s called under __del__, __del__ should be in the call stack, which would be an indicator that garbage collection is being executed.

1 Like