2010-12-10 2 views
4

exception_ptrのC++ 0x機能を使用すると、あるスレッドに例外を格納し、別のスレッドがそのスレッドにアクセスできるようになります。しかし、もう一方のスレッドはrethrow_exception()を呼び出さなければなりません。しかし、場合によっては、実際に他のスレッドを中断し、すぐに例外を発生させる必要があります。 nullでないためにexception_ptrをポーリングすることは解決策ではありません。別のスレッドでC++例外を注入する

Windowsに例外を注入する方法の解決策は、http://www.codeproject.com/KB/exception/ExcInject.aspxにあります。スレッドを一時停止し、命令ポインタレジスタを変更してから再開します。しかし、Linux上で動作させるために私のコードも必要です。どうすればそれを達成できますか?

getcontext()のようなものを使用すると、現在のスレッドのコンテキストが取得されます(WindowsではGetContext()はスレッドパラメータを受け入れます)ので、シグナルハンドラで呼び出す必要があります。しかし、私はgetcontext()/ setcontext()をシグナルハンドラで呼び出さないでください... あるいは、シグナルハンドラで直接rethrow_exception()を呼び出すことができましたが、エフェクト。中断されたスレッドは、中断がコールされたスコープのすべてのデストラクタと同じ方法で解き放たれたスタックを持ちます。

答えて

2

私はその記事をいくつか前にリンクしていましたが、少し懐疑的でした。

別のスレッドの命令ポインタを変更するアプローチは、まったく恐ろしいと感じます。中断している操作と中断した操作はまったく分かりません。中断された操作は例外を予期していない可能性があり、したがってそれ自身の後にクリーンアップする能力はありません。

Windowsでは、私がQueueUserAPCを使用して、アラート可能な待機状態に入った後に他のスレッドを正常に終了させました。私はLinuxのこれと直接的に等価なものについては知らない。

+0

ちょっと懐疑的になることは自由です。これはロシアのルーレットです。「プログラムをランダムにデッドロックする方法は?」デバッガAPI関数です。 –

+0

デッドロックが発生するのはなぜですか? –

+1

@Borislav:潜在的にロックの実行(クリーンアップ)を防ぎ、デッドロックを引き起こします。 Herb SutterはDobbs博士について記事を書いています。あなたは決してスレッドを中断してはいけません。 –

2

私は多かれ少なかれsame question hereを尋ねました。しばらくして私は良い答えを見つけました。ここにコードですが、あなたは私の答えでより多くのコメントを見つけることができます:

#include <thread> 
#include <signal.h> 
#include <unistd.h> 
#include <iostream> 

using namespace std; 

//Custom exception which is used to stop the thread 
class StopException {}; 

void sig_fun(int s) 
{ 
    if(s == SIGUSR2)throw StopException(); 
} 

void threadFunction() 
{ 
    cout<<"Thread started"<<endl; 
    try { 
     while(true) 
     { 
      //Work forever... 
      sleep(1); 
     } 
    } catch(const StopException &e) { 
     cout<<"Thread interrupted"<<endl; 
    } 
    cout<<"Thread stopped"<<endl; 
} 

int main(int argc, char *args[]) 
{ 
    //Install Signal handler function 
    signal(SIGUSR2, sig_fun); 
    pthread_t threadObject; 
    thread t([&threadObject]() 
    { 
     //Store pthread_t object to be able to use it later 
     threadObject = pthread_self(); 
     threadFunction(); 
    }); 

    string temp; 
    cout<<"Write something when you want the thread to be killed"<<endl; 
    cin>>temp; 

    //Send Signal to thread 
    pthread_kill(threadObject, SIGUSR2); 
    t.join(); 
} 
+0

ターゲットスレッドが何をしているかに関わらず、シグナルはすぐに割り込みを受けますか?つまり、sleep()呼び出しでカーネルが待機するのをブロックするのではなく、スレッドがユーザ空間の無限ループに入っている場合はどうなりますか?また、pthreadの命令ポインタを変更する方法を知っていますか? –

関連する問題