2010-12-10 4 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을 사용하여 경고 가능한 대기 상태가되면 다른 스레드를 성공적으로 중단했습니다. 나는 리눅스에서 이것에 대해 직접적으로 같은 것을 알지 못한다.

+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의 명령어 포인터를 수정하는 방법을 알고 있습니까? –

관련 문제