C++ 捕获信号:将成员函数用作信号处理程序

C++ 捕获信号:将成员函数用作信号处理程序,c++,linux,signals,C++,Linux,Signals,我有一个对象,它在一个无止境的循环中做一些工作。main()实例化对象并调用run()方法。因为我不想使用线程,所以我需要一个解决方案使我的对象停止运行。下面你可以看到我的想法 struct Foo { void run() { running = 1; while (running) do_something_useful(); std::cout << "Execution stopped

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

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

};
我现在期望的是:程序一直运行,直到我发送
SIGTERM
,它被捕获并将导致我的对象停止迭代并返回到main

我现在有两个问题:

(a) 在代码中,您看到一行标记为“Compiler Complaints”,消息如下

boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)}
boost::函数无法转换为uu sighandler_t{aka void(*)(int)}
我需要做什么改变才能让这一切顺利进行?我认为
f
就像
void f(int)
,就像信号处理程序在一些示例中得到的函数一样

(b) 对于那些想知道“那个家伙在干什么?”的人:你有什么建议如何更好地解决这类问题

  • 我需要做什么改变才能让这一切顺利进行?我认为f类似于void f(int),类似于信号处理程序在一些示例中得到的函数
编译器抱怨类型,因此需要传递函数指针,而不是类型为
boost::function
的对象。创建此类型的全局变量并添加调用此对象的函数将起作用:

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

}
boost::函数myCb;
void CallCb(int值)
{
myCb(价值);
}
int main(int argc,字符**argv)
{
富富,;
结构sigaction sigIntHandler;
myCb=std::bind1st(
std::mem_-fun(&Foo::catch_信号),&Foo);
f(5);//这个调用有效
sigIntHandler.sa_handler=CallCb;
SIGEptySet(&sigIntHandler.sa_mask);
sigIntHandler.sa_标志=0;
sigation(SIGTERM和sigintmhandler,NULL);
s、 run();
}
  • 你对如何更好地解决这类问题有什么建议吗

不是真的。这个主意还可以。我只想用c++11 lambda来代替

在信号处理程序中可以移植的东西很少。基本上,您可以在类型为
sig\u atomic\u t
的对象中存储值。例如,插入
cout
,就不必工作。如果您有C++11,您可以使用原子类型或显式fences做更多的工作,但是不需要对标准库进行任何其他调用来做任何合理的事情


这样,用所说的方法,你可以做的是写一个函数(一个自由函数或一个静态成员函数(但是这里有一个微妙的问题,C++链接:正式的静态成员函数不能工作,但实际上总是这样)调用成员函数,它将代码< >运行< /COD> > <代码> false (假设您已将运行的

类型更改为
sig_atomic_t
)。

只是出于好奇,您为什么不希望使用线程?虽然我根本没有使用boost,但我的假设是希望提供回调函数。比如启动
Foo::run()
在线程中,在
main
中捕获信号,让main调用类似
thread.terminate()
?是的,这是可能的,但我认为这太难了。这是一种确定的方法。另一种方法(在我平静的思考中)你可以有一个包含你需要的任何信息的结构,将它注册为一个线程,这样你就可以用它里面的普通主函数运行循环,信号处理程序在它自己的线程上运行,然后你只需要获取byref的值,看看是否发生了一个事件,如果发生了什么事件以及相应的响应指出
f
不是一个函数,而是一个我没有想到的对象。你能举一个例子说明如何使用c++11 lambda来实现它吗?
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();

}