在multithreading程序中捕获SIGSEGV和SIGFPE等信号

我正在尝试为在Linux上运行的程序编写一个multithreading的日志logging系统。

调用主程序线程中的日志系统将包含要login的数据的数据结构推入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中使用multithreading处理信号 ,但是我对于哪些信号是线程特定的以及如何捕捉它们一无所知。

Solutions Collecting From Web of "在multithreading程序中捕获SIGSEGV和SIGFPE等信号"

我同意这个意见:在实践中捕获和处理SIGSEGV往往是一件坏事。

SIGSEGV被传递给一个特定的线程(见这个 ),一个运行机器指令的机器访问某个非法的地址。

所以你不能运行一个专门在其他线程中捕获SIGSEGV的线程。 而你可能不能轻易使用SIGFEG(2) SIGSEGV

捕捉(并从其信号处理程序正常返回) SIGSEGV是一个复杂的和处理器的具体事情(它不能是“便携式C代码”)。 您需要检查和修改处理程序中的机器状态,即修改地址空间(通过调用mmap(2)等)或修改当前线程的寄存器状态。 因此,对SA_SIGINFO使用sigaction(2) ,并更改信号处理程序的第三个参数(类型为ucontext_t* )所指向的机器特定状态。 然后深入到处理器特定的 uc_mcontext字段中。 玩转单个寄存器等等…如果你不改变有故障的线程的机器状态,在和以前一样的情况下恢复执行(从SIGSEGV处理程序返回之后),并且立即发送另一个SIGSEGV信号。 …或者简单地说,不要从SIGSEGV处理程序正常返回(例如,使用siglongjmp(3)或中止(3)或_exit(2) …)。

即使你碰巧做了这些,但有传闻说Linux内核对这样的执行效率不是很高。 所以有传闻说在Linux上用这种方式来模仿Hurd / Mach外部寻呼机的效率并不高。 看到这个答案 …

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

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