从信号处理程序中抛出异常 [英] Throwing an exception from within a signal handler

查看:158
本文介绍了从信号处理程序中抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个图书馆处理错误报告的许多方面。我被委托将这个图书馆移植到Linux。当我的小测试套件运行时,其中一个测试失败。

  //编译器:4.1.1 20070105 RedHat 4.1.1-52 
//输出:在抛出int中止的实例之后调用终止

#include< iostream>
#include< csignal>
使用命名空间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<< 捕获例外:<< z < ENDL;
}
return 0;
}

int main()
{
try
{
test_signal();
}
catch(int& z)
{
cerr<< 捕获意外异常:<< z < ENDL;
}
return 0;
}

我的期望是捕获异常消息将显示。实际发生的是程序终止,因为没有catch处理程序似乎出现在抛出的int。



有一些关于SO的问题似乎相关。
我发现一些与之相关的Google网页。
智慧似乎归结为。


  1. Ya不能从信号处理程序中抛出异常,导致信号
    处理程序使用自己的堆栈运行,所以没有定义处理程序。

  2. Ya可以从信号处理程序中抛出异常,只需重新构建一个假的
    框架,你很好去嗯,我们一直都这么做。它适用于平台X上的

  3. Ya,以前可以使用gcc,但似乎没有任何
    更多。尝试 -fnon-call-exceptions 选项,也许这将工作



    代码在我们的AIX / TRU64 / MSVC编译器/环境。它在我们的Linux环境中失败。




我正在寻找帮助解决此问题的建议, Linux上的行为将与我的其他平台相匹配,或者可能实现相同功能的某种排序或解决方法。


让程序核心转储信号不是一个可行的选择。

解决方案

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



您可以轻松地在一个POSIX信号处理程序。一个常见的策略是在信号处理程序中设置一个类型为 sig_atomic_t 的全局标志,然后可能 longjmp 到相应的执行路径。



请参阅这里,以帮助撰写适当的信号处理程序。


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;
}

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.

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. Ya can't throw exceptions from signal handlers, cause the signal handler runs with its own stack, so there are no handlers defined on it.
  2. Ya can throw exceptions from signal handlers, just reconstruct a fake frame on the stack, and you are good to go.
  3. Ya, we do it all the time. It works for me on platform X
  4. Ya, that used to be available with gcc, but doesn't seem to work any more. Try the -fnon-call-exceptions option, maybe that will work

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


I am looking for suggestions to help resolve this issue so the library behavior on Linux will match my other platforms, or some sort or workaround that might achieve the same sort of functionality.
Letting the program core dump on signal, is not a viable option.

解决方案

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.

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.

这篇关于从信号处理程序中抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆