You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获Rust异步函数执行过程中的panic?

捕获异步函数执行时的Panic

在Rust中,异步函数的panic无法直接用std::panic::catch_unwind捕获——因为异步任务可能跨线程调度,普通的 unwind 机制覆盖不到这种场景。下面提供两种可靠的实现方式:

方法一:使用futures::future::catch_unwind

先在Cargo.toml中添加依赖:

[dependencies]
futures = "0.3"
serde_json = "1.0"

用catch_unwind包装异步任务,同时处理UnwindSafe约束:

use futures::future::catch_unwind;
use std::panic::AssertUnwindSafe;
use serde_json::Value;

// 你的异步函数
async fn a_sync_function(param1: i32, param2: i32) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
    // 模拟panic场景
    if param1 == 0 {
        panic!("invalid param1");
    }
    Ok(vec![serde_json::json!("success")])
}

async fn run() {
    let param1 = 0;
    let param2 = 10;

    // 用AssertUnwindSafe包裹异步闭包,解决UnwindSafe约束
    let result = catch_unwind(AssertUnwindSafe(async {
        a_sync_function(param1, param2).await
    })).await;

    match result {
        Ok(Ok(x)) => println!("正常结果: {:?}", x),
        Ok(Err(e)) => eprintln!("函数返回错误: {}", e),
        Err(panic_payload) => {
            // 捕获到panic,执行自定义逻辑
            eprintln!("捕获到panic: {:?}", panic_payload);
            // 在这里添加你需要执行的其他代码
        }
    }
}

#[tokio::main] // 也可使用async-std等其他异步运行时
async fn main() {
    run().await;
}

方法二:使用Tokio的任务调度捕获panic

基于Tokio运行时的话,需要先启用unwind特性(默认禁用):

[dependencies]
tokio = { version = "1.0", features = ["full", "unwind"] }
serde_json = "1.0"

通过tokio::spawn启动独立任务,再通过await捕获任务的panic:

use tokio;
use serde_json::Value;

async fn a_sync_function(param1: i32, param2: i32) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
    if param1 == 0 {
        panic!("invalid param1");
    }
    Ok(vec![serde_json::json!("success")])
}

#[tokio::main]
async fn main() {
    let param1 = 0;
    let param2 = 10;

    // 启动异步任务
    let task = tokio::spawn(async move {
        a_sync_function(param1, param2).await
    });

    match task.await {
        Ok(Ok(x)) => println!("正常结果: {:?}", x),
        Ok(Err(e)) => eprintln!("函数返回错误: {}", e),
        Err(panic_err) => {
            // 捕获到panic,执行自定义逻辑
            eprintln!("捕获到panic: {:?}", panic_err);
            // 在这里添加你需要执行的其他代码
        }
    }
}

注意事项

  • 异步运行时支持:不是所有异步运行时都支持unwind,比如Tokio默认关闭该特性,需要手动启用;
  • UnwindSafe约束:如果闭包中包含&mut T这类不自动实现UnwindSafe的类型,必须用AssertUnwindSafe标记,确保你确认该变量在unwind时是安全的;
  • 优先返回错误:除非必要,尽量用Result类型传递错误,而不是触发panic——panic应该用于处理不可恢复的错误场景。

内容的提问来源于stack exchange,提问作者frank C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:03:40