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

我有一个对象,在无尽的循环中做一些工作。 main()实例化对象并调用run()方法。 由于我不想使用线程,我需要一个解决scheme,使我的对象停止运行。 下面你看看我想出了什么。

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

如你所见,我需要asynchronous发送一个信号。 因此,我使用了一个信号处理程序和sigactionmain以下我可以想象使用。

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

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

我现在有两个问题:

(a)在代码中你看到一行标有“Compiler complains”的行,这个消息就像

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

我需要改变什么来完成这项工作? 我认为f就像void f(int)一样,就像信号处理函数在一些例子中得到的函数一样。

(b)对于那些怀疑“那个人在干什么?”的人:你有什么build议可以更好的解决这个问题吗?

  • 我需要改变什么来完成这项工作? 我认为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而已

在信号处理程序中,可以轻松地做的事情非常少。 基本上,您可以将值存储在类型为sig_atomic_t的对象中。 插入cout ,例如,不必工作。 如果你有C ++ 11,你可以使用原子类型或明确的屏蔽来做更多的事情,但是对标准库的任何其他调用并不需要做任何明智的事情。

所以说,你可以做的是编写一个函数(一个自由函数或者一个静态成员函数)(但是在C ++连接中存在一个微妙的问题:静态成员函数在形式上是行不通的,但是在实践中它总是)),它会调用成员函数,然后将running设置为false (假设您已将running类型更改为sig_atomic_t )。