c++ - 多线程程序中捕获SIGSEGV、SIGFPE等信号

标签 c++ linux multithreading posix

我正在尝试为在 linux 上运行的程序编写一个多线程日志系统。

在主程序线程中调用日志系统会将包含要记录的数据的数据结构推送到 FIFO 队列中。专用线程从队列中提取数据并输出数据,而程序主线程继续其任务。

如果主程序引发 SIGSEGV 或其他信号,我需要确保在终止之前队列为空。

我的计划是使用 pthread_sigmask http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html 来阻止信号对于除一个线程之外的所有线程,但阅读 http://man7.org/linux/man-pages/man7/signal.7.html 上的信号列表我注意到:

A signal may be generated (and thus pending) for a process as a whole (e.g., when sent >using kill(2)) or for a specific thread (e.g., certain signals, such as SIGSEGV and SIGFPE, >generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill(3)).

如果我在除专用于捕获信号的线程之外的所有线程上阻塞 SIGSEGV,它会捕获由不同线程引发的 SIGSEGV 吗?

我找到了问题 Signal handling with multiple threads in Linux ,但我对哪些信号是线程特定的以及如何捕获它们一无所知。

最佳答案

我同意评论:在实践中捕获和处理 SIGSEGV 通常是一件坏事。

并且 SIGSEGV 被传送到一个特定的 线程(参见 this ),该线程运行访问某个非法地址的机器指令。

因此您不能在其他线程中运行专用于捕获 SIGSEGV 的线程。而且您可能无法轻松使用 signalfd(2)对于 SIGSEGV...

捕获(并从其信号处理程序正常返回)SIGSEGV 是一个复杂的特定于处理器的事情(它不能是“可移植的 C 代码”)。您需要检查和更改处理程序中的机器状态,即修改地址空间(通过调用 mmap(2) 等...)或修改当前线程的寄存器状态。所以使用 sigaction(2)使用 SA_SIGINFO 并更改信号处理程序的第三个参数(ucontext_t* 类型)指向的机器特定状态。然后深入研究它的处理器特定 uc_mcontext 字段。享受更改单个寄存器等的乐趣...如果您不更改故障线程的机器状态,则会在与以前相同的情况下恢复执行(从您的 SIGSEGV 处理程序返回后),并且立即发送另一个 SIGSEGV 信号....或者简单地说,不要从 SIGSEGV 处理程序正常返回(例如使用 siglongjmp(3)abort(3)_exit(2) ...)。

即使您碰巧执行了所有这些操作,也有传言称 Linux 内核在执行此类操作时效率不是很高。因此传闻在 Linux 上尝试以这种方式模仿 Hurd/Mach 外部寻呼机效率不高。参见 this answer ...

当然,信号处理程序应该只调用(更多信息请参见 signal(7))异步信号安全函数。特别是,原则上您不能从它们调用 fprintf(并且您可能无法可靠地使用您的日志系统,但它可以在大多数但不是所有情况下工作) .

我在 SIGSEGV 上所说的内容也适用于 SIGBUSSIGFPE(以及其他线程特定的异步信号,如果它们存在的话)。

关于c++ - 多线程程序中捕获SIGSEGV、SIGFPE等信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20304720/

相关文章:

c++ - 如何应对高频数据?

不包含 C++ 头文件 - 适用于 Linux 的 C++ 示例应用程序

android - 载入画面介绍

java - 为什么这段代码不会导致竞争条件?

C++模板模板(双模板?)

C++:为什么我不能将一对迭代器传递给 regex_search?

python - 在 Ubuntu 14.04 中为 python 安装 opencv

linux - 如何授予正在运行的进程 sudo 权限

linux - 无法为 Go 游戏的服务器放置机器人

c - 主线程中的多线程矩阵乘法不会等到其他线程完成工作吗?