7

キャッチされていないスレッドからメインスレッドに例外を伝播する必要があるプログラムがあります。これにより、失敗した理由に関する情報をユーザーに提供し、安全にシャットダウンできます。私のInterThreadExceptionハンドラーは機能しているように見えますが、例外をスローするスレッドがメインスレッドによって直接生成された場合のみです。

ハンドラーはすべてのInterTheadException場合に正しく呼び出され、例外ポインターが渡されることによって例外が伝搬されたことが通知され、メインスレッドは新しい例外を受け取ったという通知を受け取りますがstd::rethrow_exception、例外ポインターでの呼び出しは単に失敗しますそして一見何もしません。これら 2 つの異なるスレッドからまったく同じ例外をスローすることをテストしましたが、何をスローしても問題は解決しないようです。

例外ポインターの使用方法について根本的な誤解があると思いますが、よくわかりません。

これが私の実装ですInterThreadExceptionHandler

class InterThreadExceptionHandler : NonCopyable
{
public:
    InterThreadExceptionHandler();
    ~InterThreadExceptionHandler();

    //
    // Sends an exception into this handler, informing it that 
    //this exception has been caught
    // and may be propagated to another thread
    //
    void sendException(std::exception_ptr exception);

    //
    // Freezes the calling thread until an exception has been sent,
    //then rethrows said exception
    //
    void waitForException();

private:
    std::vector<std::exception_ptr> sentExceptions; 
    std::mutex sentExceptionsMutex;

    Semaphore sentExceptionsCounter;
};


InterThreadExceptionHandler::InterThreadExceptionHandler()
{
}
InterThreadExceptionHandler::~InterThreadExceptionHandler()
{
}

void InterThreadExceptionHandler::sendException(std::exception_ptr exception)
{
    ScopedLock lock(this->sentExceptionsMutex);
    this->sentExceptions.push_back(exception);
    this->sentExceptionsCounter.give();
}

void InterThreadExceptionHandler::waitForException()
{
    this->sentExceptionsCounter.take();
    ScopedLock lock(this->sentExceptionsMutex);

    assert( this->sentExceptions.size() > 0 );

    std::exception_ptr e = this->sentExceptions[0];
    this->sentExceptions.erase(this->sentExceptions.begin());
    if (e == std::exception_ptr())
    {
        throw std::exception("Invalid exception propagated!");
    }
    std::rethrow_exception(e);
}
4

1 に答える 1

0

これがあなたの質問に対する直接的な回答ではないことをお詫びしますが、とにかく役立つかもしれません.

例外をキャッチしたり、リターン コードをチェックしたりして、スレッドで実行時エラーを検出した場合は、そのスレッドにプロセス全体をフリーズさせます。また、ftrace (dtrace の Linux クローン) をオフにして、取得できるトレース ログが問題に至るまで保存されるようにします。残念ながら、Windows の同等物が何であるかはわかりません。次に、デバッガーを接続して、何が起こっているかを確認し、値を修正して実行を続行することもできます。

デプロイされたコードではあまり役に立ちませんが、開発中は優れています。すべてが「そのまま」存在し、スタックの巻き戻しがなく、他のスレッドがどこにも到達する機会があまりないなど、問題に対する見方は良いです。これにより、障害の特定が容易になります。デプロイされたコードの場合、代わりにコア ダンプを誘発することがあります (私は unixy で実行する傾向があります)。ある程度のクリーンアップが必要な場合、明らかにそれは良くありません。

于 2013-03-11T07:25:00.490 に答える