Fundamentally panic recovery works the same way in all threads—for both the main thread and spawned threads the standard library implements panic handling by wrapping the user code in catch_unwind().[2][3] It's more or less possible to override the standard library's behavior for the main thread by wrapping all the code in your main() function in a catch_unwind() and then implementing whatever fallback behavior you want, like waiting for other threads to exit before terminating. In some cases something like this happens automatically, for instance if the main thread spawns other threads using std::thread::scope.[4]
[1]: https://doc.rust-lang.org/std/thread/#the-threading-model [2]: https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8d... [3]: https://github.com/rust-lang/rust/blob/7042c269c166191cd5d8d... [4]: https://doc.rust-lang.org/std/thread/fn.scope.html