在C ++中,当用ctrl-c中断时,在死亡之前调用带参数的函数(信号编号除外)

时间:2013-10-14 18:15:28

标签: c++ signals posix

我希望在程序死亡之前用ctrl-c中断时为文件写一些额外的行。但是文件的位置没有硬编码,因此我需要的不仅仅是正常的中断处理as explained here。这样做的最佳方式是什么?


动机:
我正在进行时间依赖的有限元模拟。有时我会忘记或误估合理的tmax,模拟需要很长时间才能完成,所以我用ctrl-c打断它。但是我仍然希望使用到那时为止生成的数据。特别是有一个xml文件,在模拟完成后需要添加几行来关闭标签。当然可以手工完成,但这很痛苦,所以我试着让它自动化。

2 个答案:

答案 0 :(得分:2)

根据“How can I catch a ctrl-c event? (C++)”的答案,我们可以安装一个简单引发异常的信号处理程序。然后我们可以捕获异常并运行我们喜欢的任何标准c ++代码。

这是一个有效的例子:

#include <iostream>
#include <exception>
#include <signal.h>
#include <stdlib.h>


class InterruptException : public std::exception
{
public:
  InterruptException(int s) : S(s) {}
  int S;
};


void sig_to_exception(int s)
{
  throw InterruptException(s);
}


int main()
  {
    // Taken from answer to "How can I catch a ctrl-c event? (C++)"
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = sig_to_exception;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);


    try
      {
        std::cout << "Inside try" << std::endl;

        // Do something with output so the loop doesn't get optimised out
        double i = 0;
        while(i < 1e30) {i++;} // loop until interrupted
        std::cout << i << std::endl;
      }
    catch(InterruptException& e)
      {
        std::cout << "Write something to file" << std::endl;
        std::cout << "Caught signal " << e.S << std::endl;
        return 1;
      }

    return 0;
  }

这种方法至少有一个缺点:我们必须在try中安装处理程序后包装所有内容,否则中断信号会导致abort()。

答案 1 :(得分:1)

基于循环的科学代码的一个常见方案是使用全局volatile sig_atomic_t布尔值来指示是否捕获了信号并将其添加到循环条件中。

e.g。

volatile sig_atomic_t interrupted=false; 
...
void signal_handler(int s)
{
   // ...
   interrupted=true;
}
...
while (!converged && !interrupted)
{
     // Perform computations
}
// Save file properly