首页 \ 问答 \ 为什么我会遇到Linux信号处理的意外行为?(Why am I experiencing unexpected behavior with Linux signal handling?)

为什么我会遇到Linux信号处理的意外行为?(Why am I experiencing unexpected behavior with Linux signal handling?)

我生活在Win7 / MSVC 2010sp1的环境中,两个不同的Linux盒子(Red Hat)和g ++版本(4.4.7,4.1.2),以及AIX和xlc ++(08.00.0000.0025)。

不久前,我们要求将一些代码从AIX移到Linux上。 没过多久就看到Linux有点不同了。 通常,当抛出信号时,我们处理它并抛出C ++异常。 这没有按预期工作。

长话短说,从信号处理程序抛出c ++异常是行不通的。

过了一段时间,我整理了一个使用setjmp / longjmp将异常移出处理程序的修复程序。 在所有平台上都可以进行后续测试。 经过一场强制性的立方体快乐舞会后,我开始进行一些单元测试。 哎呀。

我的一些测试在Linux上失败了。 我观察到的是,提升功能只能工作一次。 使用SIGILL进行了两次测试,第一次通过,第二次失败。 我打破了一把斧头,并开始砍掉代码以尽可能多地删除斧头。 这产生了这个较小的例子。

#include <csetjmp>
#include <iostream>
#include <signal.h>

jmp_buf  mJmpBuf;
jmp_buf *mpJmpBuf = &mJmpBuf;
int status = 0;
int testCount = 3;

void handler(int signalNumber)
{
    signal(signalNumber, handler);
    longjmp(*mpJmpBuf, signalNumber);
}

int main(void)
{
    if (signal(SIGILL, handler) != SIG_ERR)
    {
        for (int test = 1; test <= testCount; test++)
        {
            try
            {
                std::cerr << "Test " << test << "\n";
                if ((status = setjmp(*mpJmpBuf)) == 0)
                {
                    std::cerr << "    About to raise SIGILL" << "\n";
                    int returnStatus = raise(SIGILL);
                    std::cerr << "    Raise returned value " << returnStatus
                              << "\n";
                }
                else
                {
                    std::cerr << "    Caught signal. Converting signal "
                              << status << " to exception" << "\n";
                    std::exception e;
                    throw e;
                }
                std::cerr << "    SIGILL should have been thrown **********\n";
            }
            catch (std::exception &)
            { std::cerr << "    Caught exception as expected\n"; }
        }
    }
    else
    { std::cerr << "The signal handler wasn't registered\n"; }

    return 0;
}

对于Windows和AIX框,我得到了预期的输出。

Test 1
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected Test 2
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected Test 3
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected

对于两个Linux盒子,它看起来像这样。

Test 1
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected
Test 2
    About to raise SIGILL
    Raise returned value 0
    SIGILL should have been thrown **********
Test 3
    About to raise SIGILL
    Raise returned value 0
    SIGILL should have been thrown **********

所以,我真正的问题是“ 这里发生了什么?

我的修辞问题是:

  • 还有其他人观察到这种行为吗?
  • 我该怎么做才能解决这个问题?
  • 我应该注意哪些其他事情?

I live in an environment with Win7/MSVC 2010sp1, two different Linux boxes (Red Hat) with g++ versions (4.4.7, 4.1.2), and AIX with xlc++ (08.00.0000.0025).

Not so long ago it was requested that we move some code from AIX over to Linux. It didn't take too long to see that Linux was a bit different. Normally when a signal is thrown, we handle it and throw a C++ exception. That was not working as expected.

Long story short, throwing c++ exceptions from a signal handler isn't going to work.

Sometime later, I put together a fix that uses setjmp/longjmp to move the exception out of the handler. Aftersome testing and the dang thing works on all platforms. After an obligatory round of cubical happy dance I moved on to setting up some unit tests. Oops.

Some of my tests were failing on Linux. What I observed was that the raise function only worked once. With two tests using SIGILL, the first one passed, and the second one failed. I broke out an axe, and started chopping away at the code to remove as much cruft as possible. That yielded this smaller example.

#include <csetjmp>
#include <iostream>
#include <signal.h>

jmp_buf  mJmpBuf;
jmp_buf *mpJmpBuf = &mJmpBuf;
int status = 0;
int testCount = 3;

void handler(int signalNumber)
{
    signal(signalNumber, handler);
    longjmp(*mpJmpBuf, signalNumber);
}

int main(void)
{
    if (signal(SIGILL, handler) != SIG_ERR)
    {
        for (int test = 1; test <= testCount; test++)
        {
            try
            {
                std::cerr << "Test " << test << "\n";
                if ((status = setjmp(*mpJmpBuf)) == 0)
                {
                    std::cerr << "    About to raise SIGILL" << "\n";
                    int returnStatus = raise(SIGILL);
                    std::cerr << "    Raise returned value " << returnStatus
                              << "\n";
                }
                else
                {
                    std::cerr << "    Caught signal. Converting signal "
                              << status << " to exception" << "\n";
                    std::exception e;
                    throw e;
                }
                std::cerr << "    SIGILL should have been thrown **********\n";
            }
            catch (std::exception &)
            { std::cerr << "    Caught exception as expected\n"; }
        }
    }
    else
    { std::cerr << "The signal handler wasn't registered\n"; }

    return 0;
}

For the Windows and the AIX boxes I get the expected output.

Test 1
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected Test 2
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected Test 3
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected

For both Linux boxes it looks like this.

Test 1
    About to raise SIGILL
    Caught signal. Converting signal 4 to exception
    Caught exception as expected
Test 2
    About to raise SIGILL
    Raise returned value 0
    SIGILL should have been thrown **********
Test 3
    About to raise SIGILL
    Raise returned value 0
    SIGILL should have been thrown **********

So, my real question is "What is going on here?"

My retorical questions are:

  • Is anyone else observing this behavior?
  • What should I do to try to troubleshoot this issue?
  • What other things should I be aware of?

原文:https://stackoverflow.com/questions/28005187
更新时间:2022-07-26 18:07

最满意答案

GRANT CREATE PROCEDURE TO [login];
GRANT CREATE VIEW TO [login];
GRANT SELECT TO [login];

等等


GRANT CREATE PROCEDURE TO [login];
GRANT CREATE VIEW TO [login];
GRANT SELECT TO [login];

And so on

相关问答

更多

相关文章

更多

最新问答

更多
  • h2元素推动其他h2和div。(h2 element pushing other h2 and div down. two divs, two headers, and they're wrapped within a parent div)
  • 创建一个功能(Create a function)
  • 我投了份简历,是电脑编程方面的学徒,面试时说要培训三个月,前面
  • PDO语句不显示获取的结果(PDOstatement not displaying fetched results)
  • Qt冻结循环的原因?(Qt freezing cause of the loop?)
  • TableView重复youtube-api结果(TableView Repeating youtube-api result)
  • 如何使用自由职业者帐户登录我的php网站?(How can I login into my php website using freelancer account? [closed])
  • SQL Server 2014版本支持的最大数据库数(Maximum number of databases supported by SQL Server 2014 editions)
  • 我如何获得DynamicJasper 3.1.2(或更高版本)的Maven仓库?(How do I get the maven repository for DynamicJasper 3.1.2 (or higher)?)
  • 以编程方式创建UITableView(Creating a UITableView Programmatically)
  • 如何打破按钮上的生命周期循环(How to break do-while loop on button)
  • C#使用EF访问MVC上的部分类的自定义属性(C# access custom attributes of a partial class on MVC with EF)
  • 如何获得facebook app的publish_stream权限?(How to get publish_stream permissions for facebook app?)
  • 如何防止调用冗余函数的postgres视图(how to prevent postgres views calling redundant functions)
  • Sql Server在欧洲获取当前日期时间(Sql Server get current date time in Europe)
  • 设置kotlin扩展名(Setting a kotlin extension)
  • 如何并排放置两个元件?(How to position two elements side by side?)
  • 如何在vim中启用python3?(How to enable python3 in vim?)
  • 在MySQL和/或多列中使用多个表用于Rails应用程序(Using multiple tables in MySQL and/or multiple columns for a Rails application)
  • 如何隐藏谷歌地图上的登录按钮?(How to hide the Sign in button from Google maps?)
  • Mysql左连接旋转90°表(Mysql Left join rotate 90° table)
  • dedecms如何安装?
  • 在哪儿学计算机最好?
  • 学php哪个的书 最好,本人菜鸟
  • 触摸时不要突出显示表格视图行(Do not highlight table view row when touched)
  • 如何覆盖错误堆栈getter(How to override Error stack getter)
  • 带有ImageMagick和许多图像的GIF动画(GIF animation with ImageMagick and many images)
  • USSD INTERFACE - > java web应用程序通信(USSD INTERFACE -> java web app communication)
  • 电脑高中毕业学习去哪里培训
  • 正则表达式验证SMTP响应(Regex to validate SMTP Responses)