简体   繁体   English

捕获信号:使用成员函数作为信号处理程序

[英]Catching signals: Use a member function as signal handler

I have an object which does some work in an endless loop. 我有一个在无限循环中做一些工作的对象。 The main() instantiates the object and calls the run() method. main()实例化对象并调用run()方法。 Since I don't want to use threads, I need a solution to make my object stop running. 由于我不想使用线程,我需要一个解决方案来使我的对象停止运行。 Below you see what I've come up with. 下面你看看我想出了什么。

struct Foo
{
    void run()
    {
        running = 1;
        while (running) 
            do_something_useful();

        std::cout << "Execution stopped." << std::endl;
    }

    bool running;

    void catch_signal(int signal)
    {
        std::cout << "Caught signal " << signal << std::endl;
        if( signal == SIGTERM ) 
            running = false;
    }

};

As you see, I need to send a signal asynchronously. 如您所见,我需要异步发送信号。 Therefore, I use a signal handler and sigaction . 因此,我使用信号处理程序和sigaction Below the main I can imagine to use. 下面main我可以想象使用。

int main(int argc, char** argv)
{
    Foo foo;
    struct sigaction sigIntHandler;

    boost::function< void (int) > f;
    f = std::bind1st(
      std::mem_fun(&Foo::catch_signal), &foo);
    f(5);  // this call works

    sigIntHandler.sa_handler = f;           // compiler complains, "cannot assign ..."
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGTERM, &sigIntHandler, NULL);
    s.run();

}

What I would expect now: The program runs until I send SIGTERM which is caught and will cause my object to stop iteration and return to main. 我现在期望的是:程序一直运行,直到我发送被捕获的SIGTERM并且将导致我的对象停止迭代并返回到main。

I have two questions now: 我现在有两个问题:

(a) In the code you see a line marked with "Compiler complains", the message is like (a)在代码中,您看到标有“Compiler complains”的行,消息就像

boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)}

What do I need to change to make this work? 为了使这项工作,我需要改变什么? I think f is like void f(int) , like the functions the signal handler gets in some examples. 我认为f就像void f(int) ,就像信号处理程序在一些例子中得到的函数一样。

(b) For those of you who wonder "what is that guy doing?": Do you have any advice how to solve this kind of thing better? (b)对于那些想知道“那个人在做什么?”的人:你有什么建议如何更好地解决这类问题?

  • What do I need to change to make this work? 为了使这项工作,我需要改变什么? I think f is like void f(int), like the functions the signal handler gets in some examples. 我认为f就像void f(int),就像信号处理程序在一些例子中得到的函数一样。

The compiler complains about the type, therefore you need to pass a function pointer, not an object of type boost::function<void(int)> . 编译器抱怨类型,因此您需要传递函数指针,而不是boost::function<void(int)>类型的对象。 Creating a global variable of this type, and adding a function which calls this object would work : 创建此类型的全局变量,并添加一个调用此对象的函数将起作用:

boost::function<void(int)> myCb;
void CallCb( int value )
{
  myCb(value);
}

int main(int argc, char** argv)
{
    Foo foo;
    struct sigaction sigIntHandler;

    myCb = std::bind1st(
      std::mem_fun(&Foo::catch_signal), &foo);
    f(5);  // this call works

    sigIntHandler.sa_handler = CallCb;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGTERM, &sigIntHandler, NULL);
    s.run();

}
  • Do you have any advice how to solve this kind of thing better? 你对如何更好地解决这类问题有什么建议吗?

Not really. 并不是的。 The idea is ok. 这个想法没问题。 I would just just c++11 lambda instead 我只想改变c ++ 11 lambda

There is very little that you can do portably in a signal handler. 您可以在信号处理程序中轻松地进行操作。 Basically, you can store a value in an object whose type is sig_atomic_t . 基本上,您可以将值存储在类型为sig_atomic_t的对象中。 Inserting into cout , for example, doesn't have to work. 例如,插入cout不一定有效。 If you have C++11 you can do a bit more, using atomic types or explicit fences, but any other calls into the standard library aren't required to do anything sensible. 如果你有C ++ 11,你可以使用原子类型或显式围栏做更多的事情,但是对标准库的任何其他调用都不需要做任何合理的事情。

So, with all that said, what you can do is write a function (either a free function or a static member function (but there is a subtle issue here with C++ linkage: formally a static member function won't work, but in practice it always does)) that calls the member function, which in turn sets running to false (assuming you've changed the type of running to sig_atomic_t ). 所以,尽管如此,你可以做的是编写一个函数(自由函数或静态成员函数)(但这里有一个微妙的问题,C ++链接:正式的静态成员函数不起作用,但在实践中它始终会))调用成员函数,而成员函数又将running设置为false (假设您已将running类型更改为sig_atomic_t )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM