如何在线程上引起恐慌以立即结束主线程? [英] How can I cause a panic on a thread to immediately end the main thread?
问题描述
在 Rust 中,恐慌会终止当前线程,但不会发送回主线程.我们被告知的解决方案是使用 join
.但是,这会阻塞当前正在执行的线程.因此,如果我的主线程产生 2 个线程,则我无法同时加入它们并立即返回恐慌.
In Rust, a panic terminates the current thread but is not sent back to the main thread. The solution we are told is to use join
. However, this blocks the currently executing thread. So if my main thread spawns 2 threads, I cannot join both of them and immediately get a panic back.
let jh1 = thread::spawn(|| { println!("thread 1"); sleep(1000000); };
let jh2 = thread::spawn(|| { panic!("thread 2") };
在上面,如果我在线程 1 上加入,然后在线程 2 上,我将等待 1,然后才会收到来自任一线程的恐慌
In the above, if I join on thread 1 and then on thread 2 I will be waiting for 1 before ever receiving a panic from either thread
尽管在某些情况下我想要当前的行为,但我的目标是默认为 Go 的行为,在这种行为中,我可以生成一个线程并使其在该线程上发生恐慌,然后立即结束主线程.(Go 规范还记录了一个 protect
函数,因此很容易在 Go 中实现 Rust 行为).
Although in some cases I desire the current behavior, my goal is to default to Go's behavior where I can spawn a thread and have it panic on that thread and then immediately end the main thread. (The Go specification also documents a protect
function, so it is easy to achieve Rust behavior in Go).
推荐答案
已针对 Rust 1.10+ 更新,请参阅答案的先前版本的修订历史
好点,在go中主线程没有解开,程序就崩溃了,但是报了原来的panic.这实际上是我想要的行为(尽管理想情况下资源会在任何地方得到正确清理).
good point, in go the main thread doesn't get unwound, the program just crashes, but the original panic is reported. This is in fact the behavior I want (although ideally resources would get cleaned up properly everywhere).
这可以通过最近稳定的std::panic::set_hook()
函数.有了它,你可以设置一个钩子来打印恐慌信息然后退出整个过程,就像这样:
This you can achieve with the recently stable std::panic::set_hook()
function. With it, you can set a hook which prints the panic info and then exits the whole process, something like this:
use std::thread;
use std::panic;
use std::process;
fn main() {
// take_hook() returns the default hook in case when a custom one is not set
let orig_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
// invoke the default handler and exit the process
orig_hook(panic_info);
process::exit(1);
}));
thread::spawn(move || {
panic!("something bad happened");
}).join();
// this line won't ever be invoked because of process::exit()
println!("Won't be printed");
}
尝试注释 set_hook()
调用,您将看到 println!()
行被执行.
Try commenting the set_hook()
call out, and you'll see that the println!()
line gets executed.
然而,这种方法由于使用了process::exit()
,将不允许释放其他线程分配的资源.事实上,我不确定 Go 运行时是否也允许这样做;它很可能使用与中止进程相同的方法.
However, this approach, due to the use of process::exit()
, will not allow resources allocated by other threads to be freed. In fact, I'm not sure that Go runtime allows this as well; it is likely that it uses the same approach with aborting the process.
这篇关于如何在线程上引起恐慌以立即结束主线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!