SIGSEGV会被传递给每个线程吗?

19

我在Linux中有一个多线程程序。 我对某些内存区域感兴趣,想知道它们是否在特定时间段内被写入。 为此,我只给那些内存页读取权限,并安装了SIGSEGV信号处理程序。 现在我的问题是,每个线程都会为自己调用信号处理程序吗? 比如说,线程1写入一些禁止访问的内存区域,它会执行信号处理程序吗?

2个回答

30

首先

信号处理是进程级别的;一个进程中的所有线程对于每个信号共享相同的处理方式。如果某个线程使用sigaction()为,例如,SIGINT建立了一个处理程序,那么该处理程序可以从任何接收到SIGINT的线程中调用。

但请继续阅读

一个信号可能被发送到整个进程或特定线程。如果

它是在线程上下文中的特定硬件指令的执行作为直接结果生成的(SIGBUS、SIGFPE、SIGILL和SIGSEGV),则该信号是针对线程的。

我在引用TLPI的内容。


1
这意味着SIGSEGV信号处理程序将由写入禁止内存的线程执行,对吗? - MetallicPriest
@MetallicPriest 是的,但它是所有线程的相同处理程序。 - cnicutar
这还取决于哪个线程调用了mprotect吗?我认为mprotect是针对整个进程的,对吗? - MetallicPriest
2
是的。mmap、mprotect等会影响整个进程。SIGSEGV信号总是被发送到引起它的线程。 - MarkR
有没有一种方法可以强制为进程设置“通用”的SIGSEGV处理程序?或者将故障重定向到特定的处理程序?而不覆盖每个线程的默认处理程序。 - Paschalis
不太可能,值得怀疑。我不知道这个假设如何能够工作。SIGSEGV是由线程进行错误的内存访问引起的。即使有一个API来定义这样的处理程序,另一个并没有被调度运行的线程如何可能处理这个问题呢?唯一“有效”的方法是从导致访问的线程中调用处理程序。这也是唯一在逻辑上真正有意义的方法。 - Damon

6

不,根据问题标题。

对于您所询问的特定信号,是的(否则:这取决于情况)。导致段错误的线程将接收该信号。

请参见signal(7)

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 [...].

为什么你说不是,当描述中写着SIGSEGV是线程定向的? - MetallicPriest
3
因为问题涉及“对于_每个_线程”,所以SIGSEGV信号只会发送给一个线程(即导致该信号的线程)。因此,答案是否定的。(当然,如果未处理该信号,它可能(通常会)杀死整个进程,这显然会影响到每个其他线程,但信号不会被发送到每个线程。) - Damon
标题中的问题与正文中的问题不完全相符;它们都在询问同一基本信息,但对于一个问题的“否定”却是另一个问题的“肯定”。因此,您可能需要调整您的答案,以明确表明您是否回答了“否定”的那个问题。 - ruakh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接