从信号处理程序中引发异常

2022-01-08 00:00:00 signals exception c++

我们有一个处理错误报告许多方面的库.我的任务是将此库移植到 Linux.通过我的小测试套件运行时,其中一个测试失败了.测试的简化版本如下所示.

We have a library that deals with many aspects of error reporting. I have been tasked to port this library to Linux. When running though my little test suite, one of the tests failed. A simplified version of the test appears below.

// Compiler: 4.1.1 20070105 RedHat 4.1.1-52
// Output: Terminate called after throwing an instance of 'int' abort

#include <iostream>
#include <csignal>
using namespace std;

void catch_signal(int signalNumber)
{
    signal(SIGINT, SIG_DFL);
    throw(signalNumber);
}

int test_signal()
{
    signal(SIGINT, catch_signal);

    try
    {
        raise(SIGINT);
    }
    catch (int &z)
    {
        cerr << "Caught exception: " << z << endl;
    }
    return 0;
}

int main()
{
    try
    {
        test_signal();
    }
    catch (int &z)
    {
        cerr << "Caught unexpected exception: " << z << endl;
    }
    return 0;
}

我的期望是显示 Caught exception: 消息.实际发生的是程序终止,因为抛出的 int 似乎没有 catch 处理程序.

My expectation is that the Caught exception: message will be displayed. What actually happens is that the program terminates as no catch handler appears to be present for the thrown int.

有几个关于 SO 的问题似乎相关.我发现了一些相关的谷歌页面.智慧"似乎可以归结为.

There are a few questions on SO that seem related. I found a number of Google pages that were related. The 'wisdom' seems to boil down to.

  1. 你不能从信号处理程序中抛出异常,导致信号处理程序使用自己的堆栈运行,因此没有定义处理程序.
  2. 你可以从信号处理程序中抛出异常,只是重建一个假的堆栈上的框架,你很高兴.
  3. 是的,我们一直都这样做.它适用于 X 平台
  4. 是的,它曾经可用于 gcc,但似乎不起作用更多的.试试 -fnon-call-exceptions 选项,也许会起作用

代码在我们的 AIX/TRU64/MSVC 编译器/环境中按预期工作.它在我们的 Linux 环境中失败.

The code works as expected on our AIX/TRU64/MSVC compiler/environments. It fails in our Linux environment.


我正在寻找帮助解决此问题的建议,以便 Linux 上的库行为与我的其他平台相匹配,或者可以实现相同功能的某种类型或解决方法.
让程序核心转储信号,不是一个可行的选择.

推荐答案

信号与 C++ 异常完全不同.您不能使用 C++ try/catch 块来处理信号.具体来说,信号是 POSIX 概念,而不是 C++ 语言概念.信号由内核异步传递给您的应用程序,而 C++ 异常是由 C++ 标准定义的同步事件.

Signals are totally different than C++ exceptions. You can't use a C++ try/catch block to handle a signal. Specifically, signals are a POSIX concept, not a C++ language concept. Signals are delivered asynchronously to your application by the kernel, whereas C++ exceptions are synchronous events defined by the C++ standard.

您可以在 POSIX 信号处理程序中进行可移植的操作非常有限.一个常见的策略是有一个 sig_atomic_t 类型的全局标志,它将在信号处理程序中设置为 1,然后可能将 longjmp 设置为适当的执行路径.

You are quite limited in what you can do portably in a POSIX signal handler. A common strategy is to have a global flag of type sig_atomic_t which will be set to 1 in the signal handler, and then possibly longjmp to the appropriate execution path.

请参阅此处获取帮助编写适当的信号处理程序.

See here for help writing proper signal handlers.

相关文章