In contrast, Common Lisps condition system keeps all stack between throw and catch so you can resume from anywhere in between, possibly with altered code or local variables.
Basically, Common Lisps exception stack traces are interactive by default.
In contrast, Common Lisps condition system keeps all stack between throw and catch so you can resume from anywhere in between, possibly with altered code or local variables.
Basically, Common Lisps exception stack traces are interactive by default.
I know that during the exception you can pry into the variables from the stack. When do they get cleaned up?
For example the variable a is unbound and we try to add 3.
CL-USER 37 > (+ 3 a)
CL shows an UNBOUND-VARIABLE error and provides Restarts. Restart 3 is a USE-VALUE restart. Error: The variable A is unbound.
1 (continue) Try evaluating A again.
2 Return the value of :A instead.
3 Specify a value to use this time instead of evaluating A.
4 Specify a value to set A to.
5 (abort) Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
We are now in a break loop, a REPL one level deeper, in the context of the error. Let's see what the condition (-> exception) is: CL-USER 38 : 1 > :cc
#<UNBOUND-VARIABLE 8010002EC3>
we call one restart (listed above, number 3) interactively, it uses the new value and continues to compute the expression. It asks for a value. I enter 5 -> 5 + 3 = 8 CL-USER 39 : 1 > :c 3
Enter a form to be evaluated: 5
8
We can do it also programmatically. HANDLER-BIND establishes a handler for UNBOUND-VARIABLE. It invokes the restart USE-VALUE with 4 -> 3 + 4 = 7 CL-USER 40 > (handler-bind ((unbound-variable #'(lambda (c)
(invoke-restart 'use-value 4))))
(+ 3 a))
7
All this is the default behavior. There is no special "debug mode", attaching a debugger or "instrumentation of code" needed.So basically instead of registering one handler (catch block) that is responsible both for determining the proper course of action and implementing it, the condition system allows you to register multiple "restarting points" which the handler can select from when deciding how to handle the error.
One of the restarts often used in debugging is restarting any of the functions in the call chain, i.e. just trying the same thing again. But just as common is varying some parameter or local variable and then restarting the function.
An exception is raised when you attempt to parse HTML as JSON. The process doesn’t end. You catch the exception, see what happened, and respond with a 400.
Just dump the core and analyse the frozen state. One thing that annoyed me in go is that even when it core dumps on panic and after I worked on the backtrace analyser for gdb, most of the core dumps were useless as everything of worth was already unwound and lost.
[1] http://bytepointer.com/resources/pietrek_crash_course_depths...
[2] http://bytepointer.com/resources/pietrek_vectored_exception_...
You might have to use a few tricks/hacks, but I'm pretty sure you can set up python in a way to breakpoint at an exception, including all local state at the throw site. Otherwise pdb would not work.
It’s very possible to pause (pdb-like) or persist the local state/stack.
But there needs to be an actual exception.
If someone pulls the power cord, you’re out of luck.