代码之家  ›  专栏  ›  技术社区  ›  Arpegius

有时向pthread注入运行时异常失败。怎么解决?

  •  1
  • Arpegius  · 技术社区  · 16 年前

    我尝试使用信号将异常注入到线程中,但有时无法捕获异常。例如,以下代码:

    void _sigthrow(int sig)
    {
        throw runtime_error(strsignal(sig));
    }
    struct sigaction sigthrow = {{&_sigthrow}};
    
    void* thread1(void*)
    {
        sigaction(SIGINT,&sigthrow,NULL);
        try
        {
            while(1) usleep(1);
        }
        catch(exception &e)
        {
            cerr << "Thread1 catched " << e.what() << endl;
        }
    };
    
    void* thread2(void*)
    {
        sigaction(SIGINT,&sigthrow,NULL);
        try
        {
            while(1);
        }
        catch(exception &e)
        {
            cerr << "Thread2 catched " << e.what() << endl; //never goes here
        }
    };
    

    如果我试着像这样执行:

    int main()
    {
        pthread_t p1,p2;
    
        pthread_create( &p1, NULL, &thread1, NULL );
        pthread_create( &p2, NULL, &thread2, NULL );
    
        sleep(1);
    
        pthread_kill( p1, SIGINT);
        pthread_kill( p2, SIGINT);
    
        sleep(1);
    
        return EXIT_SUCCESS;
    }
    

    我得到以下输出:

    Thread1 catched Interrupt
    terminate called after throwing an instance of 'std::runtime_error'
      what():  Interrupt
    Aborted
    

    如何使第二个威胁捕获异常? 有没有更好的方法来注入异常?

    2 回复  |  直到 16 年前
        1
  •  2
  •   bdonlan    16 年前

    G++假设异常只能从函数调用中抛出。如果您要违反这个假设(例如,从信号处理程序中抛出它们),您需要通过 -fnon-call-exceptions

    但是请注意,这会导致G++:

     Generate code that allows trapping instructions to throw
     exceptions.  Note that this requires platform-specific runtime
     support that does not exist everywhere.  Moreover, it only allows
     _trapping_ instructions to throw exceptions, i.e. memory
     references or floating point instructions.  It does not allow
     exceptions to be thrown from arbitrary signal handlers such as
     `SIGALRM'.
    

    这意味着,从一些随机代码中间进行例外处理永远都不安全。你只能离开 SIGSEGV , SIGBUS ,和 SIGFPE ,只有你通过 -fnon-call异常 usleep()

    if (*(volatile int *)terminate_flag) throw terminate_exception();
    
        2
  •  1
  •   Eddy Pronk    16 年前