I am having a weird problem. I have some code (bpaste.net/show/75094/ ) where the main function is supposed to exit after doing some print statements. The print statements execute just fine, but then python just sits there spinning in the CPU, making my laptop fan turn on. I tried putting in exception-raising statements, but it doesn’t raise them. I tried putting return, exit(), but it just hangs after the print statements.
I put in an IPython.embed() before the function return and poked around. Apparently I needed to manually .Close() some ROOT.TFiles and some ROOT.TCanvases that I had put into python lists. After manually removing them (in the script), the function returns fine and python quits. Is this some problem in the ROOT memory management? I thought I didn’t have to Close/Delete any objects if I didn’t explicitly take ownership of them.
PyROOT runs an atexit() that closes all ROOT files, so I can see how this can make a difference. However, there’s nothing intensive (supposed to be) going on wrt. the garbage collector. At least, nothing that would not happen w/o a Close() call.
Do you know (e.g. by attaching gdb and looking at the call stack) whether the spinning happens purely in C++, or in Python, or in both?
should still be fine, even w/o debugging symbols, as the function calls (available as linker symbols) should still show up. Assuming this is Linux or Mac, one way is, when the process hangs, to use “ps -u | grep python” to find the process id (pid) of the process, then run "gdb -p " and on the gdb prompt, type “where”, which should give the trace of what it was doing at the point gdb attached.
If it does not look like it’s in a loop, type “cont”, then hit ^C at some later point which brings you back to the gdb prompt, and then try “where” again. That should allow for quickly finding where it is spinning.
every TObject derived class can notify registered handlers that it’s going dodo-bird (see the TObject dtor). The RecursiveRemove() function of all these registered handlers is then called. This communication prevents dangling pointers, as container-like objects get a chance to nullify their held pointers.
If there are many objects that do this in their dtors and many objects that listen (the open TFile’s and TCanvas’s that you mentioned all register a handler), then this can be rather slow (basically NxM, with N the number of objects, and M the number of handlers), but it should not hang forever.
I don’t think it’s recursing ad infinitum, as the trace would not end up back in the python interpreter.