如何在C++函数中防止中断?

vfh0ocws  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(176)

我在Linux中运行了一个长时间的计算,并且不时地保存部分结果。我想防止在保存部分结果的函数中出现中断:例如,如果用户按下CTRL-C,我希望函数结束,然后程序停止运行)。
例如,在下面的代码中,我希望每个“Saving...”后面都跟着一个“Done”。

#include <iostream>

void save_result(int i) {
  disable_interruptions();  // WHAT SHOULD I PUT HERE?

  std::cout << "Saving...";
  /* open some files, edit them depending on i, etc. */
  std::cout << "Done\n";

  enable_interruptions();   // WHAT SHOULD I PUT HERE?
}

int main() {
  while(true) {
    int i = 1;  /* some long computation */
    save_result(i);
  }
}

字符串
我尝试的是:

  • 使用文件原子性的一些属性。不幸的是,我必须在各个地方更改许多文件,我不能同时做所有的更新。
  • 复制文件,编辑副本,自动移回原始位置。文件太大了,而且会花太多时间。
pes8fvy9

pes8fvy91#

理想的解决方案实际上是屏蔽掉信号,而不是捕获信号并重新提升它,这将导致内核将其排队。一旦你摘下面具,信号就会发出。下面是一个示例:

#include <signal.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <iostream>
#include <string>

int main() {
    std::cout << "Masking out all signals\n";
    sigset_t oldset, newset;
    sigfillset(&newset);
    if (sigprocmask(SIG_SETMASK, &newset, &oldset) < 0) {
        perror("sigprocmask");
        exit(1);
    }
    std::cout << "Press enter to continue\n";
    std::string s;
    std::getline(std::cin, s);
    std::cout << "Unmasking..." << std::endl;
    sigprocmask(SIG_SETMASK, &oldset, NULL);
}

字符串
在多线程程序中,使用pthread_sigmask。当一个信号指向整个进程时(例如,终端生成的SIGINT),它可以由一个没有屏蔽该信号的线程来处理。

kcwpcxri

kcwpcxri2#

第512章谢谢你给我指明了方向我们可以使用信号处理器捕获停止程序的操作,并在完成更新后重新引发信号。代码:

#include <atomic>
#include <iostream>
#include <signal.h>

// The signal that we received.
// We use a global variable for simplicity, in reality it's better
// to wrap it in a class. We use an atomic in case multiple signals
// come at the same time (not sure if it's really needed). 
std::atomic_int received_signal = NSIG;

void SignalHandler(int signal) {
  received_signal = signal;
}

void save_result(int i) {
  // From now on, instead of killing the program, these actions
  // will trigger our signal handler.
  signal(SIGINT, SignalHandler);   // CTRL-C
  signal(SIGHUP, SignalHandler);   // Close terminal
  signal(SIGQUIT, SignalHandler);  // CTRL-/

  std::cout << "Saving...";
  /* open some files, edit them depending on i, etc. */
  std::cout << "Done\n";

  // Reset these actions to default behavior.
  signal(SIGINT, SIG_DFL);
  signal(SIGHUP, SIG_DFL);
  signal(SIGQUIT, SIG_DFL);

  if (received_signal != NSIG) {
    raise(received_signal);
  }
}

字符串
其他链接:

相关问题