c++ - 向 pthread 注入(inject)运行时异常有时会失败。如何解决?

标签 c++ pthreads signals

我尝试使用信号将异常注入(inject)线程,但有时异常未被捕获。例如下面的代码:

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

如何让第二个威胁捕获异常? 关于注入(inject)异常有更好的主意吗?

最佳答案

G++ 假定异常只能从函数调用中抛出。如果您要违反此假设(例如,通过将它们从信号处理程序中抛出),您需要在构建程序时将 -fnon-call-exceptions 传递给 G++。

但是请注意,这会导致 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'.

这意味着从一些随机代码中间抛出异常是不安全的。您只能排除 SIGSEGVSIGBUSSIGFPE,并且只有当您通过 -fnon-call-exceptions 并且它们是由于运行代码中的错误而触发的。这在线程 1 上起作用的唯一原因是,由于 usleep() 调用的存在,G++ 被迫假设它可能会抛出异常。对于线程 2,G++ 可以看到不存在陷阱指令,并消除 try-catch block 。

您可能会发现 pthread 取消支持更符合您的需要,或者只需在某处添加这样的测试:

if (*(volatile int *)terminate_flag) throw terminate_exception();

关于c++ - 向 pthread 注入(inject)运行时异常有时会失败。如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2696171/

相关文章:

c++,linux,如何解释 `stat64` 中文件的模式?

c++ - 指向成员函数的函数指针

c - g++ ubuntu 多线程未定义引用

linux - 在 Linux 上显式调用 SIG_DFL/SIG_IGN 处理程序

python - 在 Django 中,如何立即将组的创建者添加到该组?

c - 信号——c99 与 gnu99

c++ - B样条曲线

c++ - 使用 std c++11 智能指针转换为非标量类型

c - Pthread 传递参数

c++ - pthreads_cond_wait 和排队 pthreads 的问题