11

Duktape JavaScript インタープリターの Rust ラッパーに取り組んでいます。通常の使用例では、コール スタックは次のようになります。

  1. Rust: 任意のアプリケーション コード。
  2. Rust: 私のライブラリ ラッパー。
  3. C: Duktape の通訳者です。
  4. Rust: 私の Rust コード。
  5. Rust: アプリケーション コードへの任意のコールバック。

(5) が を呼び出すとどうなりますpanic!か? IRC のさまざまな Rust 開発者によると、panic!(3) のような非 Rust コールフレーム内からの試行は、未定義の動作を引き起こす可能性があります。

しかし、Rust のドキュメントによると、a をキャッチする唯一の方法は、追加のスレッドを生成するpanic!を使用することです。std::task::tryrustrt::unwind::tryの制限の中でも特に、1 つのスレッド内で 2 回入れ子にすることはできません。

Benjamin Herr によって提案された 1 つの解決策は、(5) のコードがパニックになった場合にプロセスを中止することです。私は彼のソリューションを としてパッケージ化しましたがabort_on_panic、「プログラム全体をクラッシュさせますが、少なくとも物事を微妙に破壊することはありません」を含む「仕事」の値に対して、うまくいくようです:

abort_on_panic!("cannot panic inside this block", {
    panic!("something went wrong!");
});

std::task::tryしかし、スレッド/タスク作成のオーバーヘッドなしでエミュレートする方法はありますか?

4

2 に答える 2

9

panic::catch_unwindRust 1.9.0 の時点で、エラーを回復するために使用できます。

use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        panic!("oh no!");
    });
    assert!(result.is_err());
}

次のレイヤーに渡すのは、次のように簡単panic::resume_unwindです。

use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        panic!("oh no!");
    });

    if let Err(e) = result {
        panic::resume_unwind(e);
    }
}
于 2016-03-19T15:59:33.573 に答える