6

私は、比較的大ざっぱな、または危険なプラットフォーム固有の作業を行うサードパーティのライブラリにさまざまなタスクを委託しているライブラリに取り組んでいます。(具体的には、LLVM や libjit などの JIT コンパイラを呼び出してマシン コードを構築する数学関数パーサーを作成しています。) 実際には、これらのサードパーティ製ライブラリはクラッシュする傾向があります (一部は私のせいです)。 、もちろん、しかし私はまだいくつかの保険が欲しい)。

次に、私のコードの残りの部分 (または私のライブラリ関数を呼び出すユーザーのコード) をダウンさせることなく、恐ろしく死んでいくジョブ (SIGSEGV、SIGILL など) を非常に優雅に処理できるようにしたいと考えています。明確にするために、その特定のジョブが続行できるかどうかは気にしません (クラッシュ状態を修復しようとするつもりはありません)。また、そのようなクラッシュの後のオブジェクトの状態についてもあまり気にしません (破棄します)。クラッシュが発生した場合はすぐにそれらを削除します)。クラッシュが発生したことを検出し、クラッシュがプロセス全体を停止するのを止め、クラッシュしているものの呼び出しを停止し、実行を再開できるようにしたいだけです。

(もう少し詳しく説明すると、現在のコードは for ループであり、利用可能な JIT コンパイラをそれぞれテストしています。これらのコンパイラの一部はクラッシュする可能性があります。クラッシュした場合は、continue;別のコンパイラを実行してテストを続けたいと思います。 )

現在、signal()かなりひどく失敗するベースの実装があります。もちろん、シグナル ハンドラのアウトは未定義の動作longjmp()であり、シグナル ハンドラはexit()orで終わることがほとんど期待されていterminate()ます。コードを別のスレッドに投げ込むだけでは、少なくとも私がこれまでにテストした方法では役に立ちません。また、C++ 例外を使用してこれを機能させる方法をハックすることもできません。

では、特定の一連の命令/スレッド/ジョブをクラッシュから隔離する最善の方法は何でしょうか?

4

4 に答える 4

11

新しいプロセスを生成します。

于 2010-08-24T15:20:03.710 に答える
5

ジョブが成功したときにどのような出力を収集しますか?

出力が低帯域幅の場合、各ジョブを独自のプロセスで実行したくなるからです。

起動するこれらのクラッシュするジョブはそれぞれ、プロセスの他の場所で使用されているメモリを破損する可能性が高くなります。

プロセスは最高の保護を提供します。

于 2010-08-24T15:20:46.453 に答える
1

プロセスは最善の保護を提供しますが、それができない可能性があります。

スレッドのエントリ ポイントが (Windows の世界などで) 自分で作成した関数である場合は、それらをブロックThreadProcでラップできます。try{...}catch(...)例外が発生したことを伝えたい場合は、特定のエラー コードをメイン スレッドに戻すか、他のメカニズムを使用できます。例外が発生したことだけでなく、その例外が何であったかをログに記録する場合は、特定の例外の種類をキャッチし、それらから診断情報を抽出して、メイン スレッドに通信する必要があります。アラ:

int my_tempermental_thread()
{
  try
  {
    // ... magic happens ...
    return 0;
  }
  catch( const std::exception& ex )
  {
    // ... or maybe it doesn't ...
    string reason = ex.what();
    tell_main_thread_what_went_wong(reason);
    return 1;
  }
  catch( ... )
  {
    // ... definitely not magical happenings here ...
    tell_main_thread_what_went_wrong("uh, something bad and undefined");
    return 2;
  }
}

このようにすると、例外が発生したときにホスト プロセスが停止するリスクがあることに注意してください。あなたは問題を修正しようとしているわけではないと言いますが、たとえば、悪意のあるスレッドがスタックを食べていないことをどのように知ることができますか? キャッチ アンド 無視は、恐ろしく混乱させるバグを作成する優れた方法です。

于 2010-08-24T17:03:56.787 に答える
0

Windows ではVirtualProtect(YourMemory, PAGE_READONLY)、信頼できないコードを呼び出すときに使用できる場合があります。このメモリを変更しようとすると、構造化例外が発生します。これを安全にキャッチして、実行を続行できます。ただし、そのライブラリによって割り当てられたメモリはもちろん、他のリソースと同様にリークします。Linux に相当するものはmprotect(YorMemory, PROT_READ)、SEGV を引き起こす です。

于 2010-08-25T09:34:44.217 に答える