捕捉信号:使用成员函数作为信号处理程序 [英] Catching signals: Use a member function as signal handler

查看:757
本文介绍了捕捉信号:使用成员函数作为信号处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象,它在无限循环中做一些工作。 main()实例化对象,并调用 run()方法。因为我不想使用线程,我需要一个解决方案,使我的对象停止运行。下面你看到我想出来的。

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

std :: cout<< 执行已停止。 << std :: endl;
}

bool running;

void catch_signal(int signal)
{
std :: cout< 捕获信号<信号<< std :: endl;
if(signal == SIGTERM)
running = false;
}

};

如您所见,我需要异步发送信号。因此,我使用信号处理程序和 sigaction 。在 main 下面我可以想象使用。

  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; //编译器抱怨,不能分配...
sigemptyset(& sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGTERM,& sigIntHandler,NULL);
s.run();

}

我现在希望:程序运行,直到我发送 SIGTERM 被捕获,将导致我的对象停止迭代并返回主。





(a)在代码中,您看到一条标有Compiler complains的行,消息类似于

  boost :: function< void(int)>不能转换为__sighandler_t {aka void(*)(int)} 

使这项工作?我认为 f 就像 void f(int),类似于信号处理程序在一些例子中的函数。 p>

(b)对于那些想知道那个家伙在做什么?的人:你有什么建议如何更好地解决这种事情吗?

解决方案



  • 我需要改变什么才能使这项工作?我认为f就像void f(int),就像信号处理程序在一些例子中获得的函数一样。


编译器会提示类型,因此您需要传递一个函数指针,而不是类型 boost :: function< void(int)> 的对象。创建这种类型的全局变量,并添加一个调用此对象的函数:

  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();

}





    <

没有什么建议。这个想法是确定。我只是只是c ++ 11 lambda代替


I have an object which does some work in an endless loop. The main() instantiates the object and calls the run() method. 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. Below the main I can imagine to use.

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.

I have two questions now:

(a) In the code you see a line marked with "Compiler complains", the message is like

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.

(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?

解决方案

  • 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.

The compiler complains about the type, therefore you need to pass a function pointer, not an object of type 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

这篇关于捕捉信号:使用成员函数作为信号处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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