如何在线程上引起恐慌以立即结束主线程? [英] How can I cause a panic on a thread to immediately end the main thread?

查看:43
本文介绍了如何在线程上引起恐慌以立即结束主线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆