2013-03-05 8 views
7

私は、キャッチされていないスレッドからメインスレッドに例外を伝播する必要があるプログラムを持っています。私のInterThreadExceptionハンドラは動作しているようですが、例外をスローするスレッドがメインスレッドによって直接生成されたときだけです。std :: rethrow_exceptionはネストされたスレッドで失敗します

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); 
} 
+1

可能性のある複製http://stackoverflow.com/questions/233127/how-can-i-propagate-exceptions-between-threads – engineerC

+3

あなたのクラスはGNU/Linux上のGCC( 'count()'の変更後にうまく動作します。非標準のstd :: exceptionコンストラクタへの呼び出しを変更し、 'Semaphore'を' std :: condition_variable'に置き換えて)MSVCバグのように聞こえるようにします。スレッドが 'main'スレッドか他のスレッドによって生成されるかどうかは関係ありません。 –

+0

vs2013で動作しますか? –

答えて

0

ご迷惑をおかけして申し訳ありませんが、とにかく参考になる場合があります。

スレッドで実行時エラーが検出された場合、例外をキャッチしたり、戻りコードなどをチェックしたりすると、そのスレッドはプロセス全体をフリーズさせます。私はftracing(dtraceのLinuxクローン)をオフにして、私が得ることができるトレースログが問題の原因となるまで保存されるようにします。私はWindowsと同等のものが何であるか分からないのではないかと心配しています。私はデバッガを接続して、何が起こっているかを見て回り、多分値を修正して実行を続けます。

デプロイされたコードではそれほど役に立ちませんが、開発中は素晴らしいです。すべてが「そのまま」あるため、スタックの巻き戻しがなく、他のスレッドはどこにでも入る機会があまりありませんでしたので、障害の識別が容易になります。デプロイされたコードの場合、私はコアダンプを引き起こすかもしれません(私は何かunixy上で動作する傾向があります)。明らかに、ある程度のクリーンアップが必要であれば、それはうまくいかない。

関連する問題