You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Linux环境下的C++函数中避免中断?

问题

在Linux系统中运行长时间计算任务时,会定期保存部分计算结果。希望确保保存结果的函数不被中断——比如用户按下CTRL-C时,要让该函数执行完成后再终止程序。

示例代码如下,要求每次输出“Saving...”后必须输出“Done”:

#include <iostream>

void save_result(int i) {
  disable_interruptions();  // 这里该写什么?

  std::cout << "Saving...";
  /* 打开文件、根据i编辑内容等操作 */
  std::cout << "Done\n";

  enable_interruptions();   // 这里该写什么?
}

int main() {
  while(true) {
    int i = 1;  /* 一些耗时的计算 */
    save_result(i);
  }
}

已尝试的方案:

  • 利用文件原子性特性,但需要修改多个不同位置的文件,无法同时完成所有更新。
  • 复制文件、编辑副本后原子性移回原位置,但文件体积过大,耗时太长。
解决方案

在Linux下,你可以通过信号掩码临时阻塞SIGINT信号(对应CTRL-C),让save_result执行期间不会被中断,完成后再恢复信号处理逻辑。

实现代码

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

// 全局终止标志,用于优雅退出循环
static bool g_terminate = false;

void save_result(int i) {
    sigset_t block_set, old_set;

    // 初始化信号集,添加需要阻塞的SIGINT
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);

    // 阻塞SIGINT,同时保存当前的信号掩码到old_set
    sigprocmask(SIG_BLOCK, &block_set, &old_set);

    std::cout << "Saving...";
    /* 这里执行文件打开、编辑等保存操作 */
    std::cout << "Done\n";

    // 恢复原来的信号掩码,允许SIGINT再次触发
    sigprocmask(SIG_SETMASK, &old_set, nullptr);
}

// SIGINT信号处理函数:提示用户并设置终止标志
void sigint_handler(int sig) {
    std::cout << "\n收到中断信号,将在当前保存完成后退出\n";
    g_terminate = true;
}

int main() {
    // 注册SIGINT的自定义处理函数
    struct sigaction sa;
    sa.sa_handler = sigint_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, nullptr);

    while(!g_terminate) {
        int i = 1;  /* 执行耗时计算 */
        save_result(i);
    }

    std::cout << "程序已退出\n";
    return 0;
}

关键说明

  1. sigprocmask的作用:
    • SIG_BLOCK:将SIGINT加入当前阻塞信号集,临时屏蔽CTRL-C的触发。
    • SIG_SETMASK:恢复之前保存的信号掩码,让SIGINT重新生效。
  2. 优雅退出逻辑:通过全局标志g_terminate,让程序在收到中断信号后,完成当前保存操作再退出循环,避免强制终止。
  3. 注意事项:
    • 不要让save_result的阻塞阶段执行过长时间,否则用户按下CTRL-C后会出现短暂无响应。
    • 如果需要屏蔽其他终止信号(如SIGTERM),可以将其添加到block_set中。

内容的提问来源于stack exchange,提问作者Michele Borassi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:36:44