Scope panics to processes, not programs
Summary
Panics should be scoped to processes, instead of entire programs. A process-wide "panic hook" can be provided, which will be executed when a process panics. After the hook finished executing (if there was one), the process will terminate. The latter is important: because of the panic, a process may be in a broken state. If a process tries to keep running, this could lead to all sorts of nasty issues.
By scoping panics to a process, programs become more resillient. This same approach is taken by Erlang and Go, though Go offers more fine-grained recovery of panics. Such fine-grained recovery is not desired in Inko, as it can lead to misuse. Midori also uses a similar mechanism.
Motivation
Currently a panic terminates the entire program, requiring external tooling (e.g. runit) to handle this. Standard procedure is to restart the program, but this can be very expensive. Scoping panics to processes still gives us all the benefits of panicking, while still allowing easy (and less resource intensive) recovery.
Implementation
Each process will have a panic_hook
field in the LocalData
structure of a
process. This is a block (block::Block
in IVM) that will be executed upon a
panic. Its first and only argument is a String that describes the panic. The
block is executed in the context of the panicking code, without unwinding the
call stack. This allows the process to retrieve a backtrace to the source of the
panic, instead of the VM having to provide this. This in turn means we can use
the runtime for this, in particular the std::debug
module.
A panic hook can be registered using the ProcessSetPanicHook
instruction.
Newly registered hooks will overwrite previous ones. The runtime will require
the provided block to be a lambda
.
Once a panic hook finishes execution, or if no hook is provided, the process will terminate. If process 0 exits, so does the entire program. Not doing so could lead to a program hanging (especially noticeable if it's a CLI application) upon a panic, if other processes are still running.
If a process has a panic hook registered, no output is written to STDERR for the panic. If no hook is registered, the currently used panic backtrace is displayed.
Drawbacks
A panic in process 0 taking down the entire program could be deemed undesirable, but it's easy to work around: just do your work in another process. It also matches the current setup of process 0 terminating successfully leading to the program's termination. This is similar to many other languages where the main thread's termination results in the program terminating.
Related work
- Midori calls this abandonment: http://joeduffyblog.com/2016/02/07/the-error-model/
- https://blog.golang.org/defer-panic-and-recover