c++ - 捕捉信号并向用户报告问题的便携方式

标签 c++ c posix signals reentrancy

如果奇迹般地在我们的程序中发生段错误,我想捕获 SIGSEGV 并通过单个返回码让用户(可能是 GUI 客户端)知道发生了严重的问题。同时我想在命令行上显示信息以显示捕获到哪个信号。

今天我们的信号处理程序如下所示:

void catchSignal (int reason) {
  std :: cerr << "Caught a signal: " << reason << std::endl;
  exit (1);
}

我可以听到上面的恐怖尖叫声,正如我从这篇文章中读到的thread从信号处理程序调用不可重入函数是邪恶的。

是否有一种便携的方式来处理信号并向用户提供信息?

编辑:或者至少在 POSIX 框架内可移植?

最佳答案

table列出了 POSIX 保证异步信号安全的所有函数,因此可以从信号处理程序调用。

通过使用此表中的“写入”命令,以下相对“丑陋”的解决方案有望解决问题:

#include <csignal>

#ifdef _WINDOWS_
#define _exit _Exit
#else
#include <unistd.h>
#endif

#define PRINT_SIGNAL(X) case X: \
          write (STDERR_FILENO, #X ")\n" , sizeof(#X ")\n")-1); \
          break;

void catchSignal (int reason) {
  char s[] = "Caught signal: (";
  write (STDERR_FILENO, s, sizeof(s) - 1);
  switch (reason)
  {
    // These are the handlers that we catch
    PRINT_SIGNAL(SIGUSR1);
    PRINT_SIGNAL(SIGHUP);
    PRINT_SIGNAL(SIGINT);
    PRINT_SIGNAL(SIGQUIT);
    PRINT_SIGNAL(SIGABRT);
    PRINT_SIGNAL(SIGILL);
    PRINT_SIGNAL(SIGFPE);
    PRINT_SIGNAL(SIGBUS);
    PRINT_SIGNAL(SIGSEGV);
    PRINT_SIGNAL(SIGTERM);
  }

  _Exit (1);  // 'exit' is not async-signal-safe
}

编辑:在 Windows 上构建。

尝试构建这个窗口后,似乎未定义“STDERR_FILENO”。然而,根据文档,它的值似乎是“2”。

#include <io.h>
#define STDIO_FILENO 2

编辑:也不应从信号处理程序调用“exit”!

正如 fizzer 指出的那样,上面调用_Exit是对HUP和TERM等信号的大锤做法。理想情况下,当捕获到这些信号时,可以使用“volatile sig_atomic_t”类型的标志来通知主程序它应该退出。

我发现以下内容对我的搜索很有用。

  1. Introduction To Unix Signals Programming
  2. Extending Traditional Signals

关于c++ - 捕捉信号并向用户报告问题的便携方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/103280/

相关文章:

c - 如何在 C 中创建字符串数组?

c - 生成文件结构

c - 如何获取与终端关联的 session 的 session ID?

c++ - 如何在 Linux 中获取 C/C++ 中的用户名?

posix - 从 posix::pwd::getpwnam_r 中提取 pw_dir

c++ - 指向 map 的指针

c++ - std::chrono::system_clock 使用什么精度?

c - Strptime开源代码未实现

c++ - 传递我的引用 C++ 时使用类的公共(public)函数时出错

c++ - win32 服务中的定时器