Background: Way back in 2001, we had a c++ consultant who thought it was a good idea to spawn a new linux thread to process each packet that came into the system, because creating linux pthreads had been ‘optimized’ by the kernel. This was a system that processed raw packets at wire speed. Needless to say, that performance sucked, and we ripped the thread spawning out.
So tying panic unwinding to an expensive resource (an os thread) is far, far from a zero cost abstraction - it costs time to create, destroy, and context switch among threads - and I would assume it is not technically necessary, as a task context is mainly a memory arena.
Yet, I think many people like to split up their programs into major areas: for example: input, process, and output. This goes for both a web server and a CLI program. If the ‘process’ part panics, the program can still write a short message out like ‘the request id X was valid input but failed to process, please try again’ to the user or system log before exiting.
The fastest and easiest way to do that would be something like:
fn main() {
...
// Start the do_process_request function, using this same stack.
// we will block until it returns. Vfork doesn't actually create a thread or call os::vfork,
// it just sets up a new memory arena and unwinding context
let result_or_panic_object = Thread::vfork(do_process_request);
if result_or_panic_object.is_err() {
println!("we had an internal error processing request id {}, URL {}, please try again!", my_request_id, my_parsed_url);
exit(1); // or http_code = 500;
}
}
This works whether or not a ‘rich object’ is returned by panicing; we know what major piece of code failed and that alone is useful. So in conclusion, if you are going to allow unwinding, please make it useful and not coupled to very expensive OS thread creation/destruction/context switching.