Inspecting the stack

Hello,

Is there any way to inspect the stack when an exception is thrown? This was my top debugging tool in Python and Common Lisp, and I really miss it in Julia. To be clear, I mean going up and down stack frames, and printing the value of local variables in those frames. Even just getting access to the function arguments would be invaluable.

Cédric

1 Like

I was thinking of a special mode in julia , where each function is replaced by an anonymous module or a closure
(I don’t think thee is a big difference between the 2) .

I think what’s blocking this , is the fact there is no way to un-load modules.

Gallium (with breakpoint_on_error()) might be what you are looking for. I have no idea how stable it is, though.

Gallium crashes on my system, but you’re right: it has a function to go to arbitrary frames.

catch_stacktrace() can give me the latest error’s stack-trace. Is there any way to access a StackFrame’s local argument values? Or are they lost during the stack unwind? If so, how come the trace’s function signatures are recoverable?

You can know the signature from the function pointer. Recovering local variables is much harder and can be impossible if we unwind through certain C libraries.

That makes sense. I suppose the best starting point for this would be Gallium.jl?

I’d like to get a reality check. My understanding right now is that when an exception is triggered, the stack is unwound, meaning that all kinds of finalizer code is run on the way back down, and the stack pointer points to the base of the stack in the absence of exception handlers. Does Julia make a copy of the stack before unwinding the stack? If not, how can catch_stracktrace confidently recover the last trace, given that other functions (eg. finalizers) may have been called, and overwritten parts of the stack?

There are obvious candidates in my mind for “C libraries” (PyCall, RMath, …) Are there instances of “pure, non-mathematical Julia code” that get compiled into C-calls with Julia callbacks?

Yes.

In C++ yes, not in julia. Finalizers only run when the GC triggers.

No.

Finalizers are irrelevant. We do SJLJ exception handling and we collect a backtrace before unwinding. We are considering copying the stack instead since it could be faster when we don’t need the backtrace.

Not really sure what you mean, julia code won’t be compiled into C code.

Sorry, I misspoke, I didn’t mean GC finalizers; I meant the “finally” part of a try-catch-finally. Thank you for the SJLJ pointer, it makes sense.

Couldn’t you compute the backtrace from the copy of the stack?

The finally is actually a catch and rethrow, in general though, by the time you unwind the stack the old stack is destroyed so it doesn’t really need to run anything to destroy it (the code you run to inspect the stack after unwinding will destroy the old stack for you).

Yes? And that’s why we are considering it.

1 Like