在多线程程序中捕获SIGSEGV和SIGFPE等信号
Catching signals such as SIGSEGV and SIGFPE in multithreaded program
我正试图为在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我注意到:
可以为整个进程(例如,当使用kill(2)发送>时)或为特定线程(例如,由于执行特定机器语言指令而生成的某些信号,如SIGSEGV和SIGFPE,>线程导向的,以及使用pthread_kill(3)针对特定线程的信号)
如果我在除一个专门捕获信号的线程外的所有线程上阻止SIGSEGV,那么它会捕获另一个线程引发的SIGSEGV吗?
我发现了Linux中多线程的信号处理问题,但我不知道哪些信号是线程特定的,以及如何捕捉它们。
我同意这些评论:在实践中,捕获和处理SIGSEGV
通常是一件坏事。
SIGSEGV
被传递到特定的线程(请参阅此),该线程运行访问某些非法地址的机器指令。
因此,您无法在其他线程中运行专门用于捕获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/Machi外部寻呼机的效率不是很高。看到这个答案。。。
当然,信号处理程序应该只调用异步信号安全函数(更多信息,请参阅信号(7))。特别是,原则上不能从它们调用fprintf
(您可能无法可靠地使用日志系统,但它可以在大多数情况下工作,但不是所有情况下都可以)。
我在SIGSEGV
上所说的内容也适用于SIGBUS
和SIGFPE
(以及其他线程特定的异步信号,如果存在的话)。
- Qt VTK交互风格的信号到小部件
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 线程之间的布尔停止信号
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 有可能在信号处理程序中设置promise吗
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- 在条件变量中触发错误信号的频率是多少
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 调试和自由执行中的信号处理
- 升压信号2将插槽传递到成员功能以断开连接
- C++函数包装器来捕获某些信号
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- 中止信号来自 C++ 中的中止(3) (SIGABRT)
- Qt将信号与另一个类方法连接
- C++ 信号和插槽不工作:插槽不响应事件
- 在多线程程序中捕获SIGSEGV和SIGFPE等信号
- 如何将SIGFPE与信号一起使用