Linux 内核何时将 SIGSEGV 的信号处理程序重置为 SIG_DFL?
When will Linux kernel reset the signal handler for SIGSEGV to SIG_DFL?
如果我为 SIGSEGV
设置了信号处理程序,则会生成如下分段错误:
int *a = NULL;
*a = 1;
将调用处理程序,但此信号处理程序只会调用一次。所以,我猜 Linux 内核会将信号处理程序重置为 SIG_DFL
,但是什么时候?我想知道细节,所以我查看了Linux内核源代码,但还没有找到线索。如果您知道详细信息,请告诉我代码。
这取决于您如何注册信号处理程序。
使用 sigaction
而没有 SA_RESETHAND
标志,将不会重置为 SIG_DFL
(尽管从信号处理程序 运行 返回以响应 SIGSEGV
交付到期到分段错误在技术上是 UB)。
使用 SA_RESETHAND
它将被重置,如果您使用 signal
注册处理程序,则未指定是否重置处理程序(因此不要使用 signal()
)。
示例:
#include <signal.h>
#include <unistd.h>
int volatile*a;
void h(int Sig) { write(1,"h\n", 2); }
int main()
{
//sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h}, 0); //won't reset the handler, will likely loop
sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h,.sa_flags=SA_RESETHAND}, 0); //will reset the handler
//signal(SIGSEGV,h); //may or may not reset the handler
*a=1;
return 0;
}
正如@PSkocik 正确回答的那样,在正常情况下,内核不会费心将信号操作更改为默认值,除非用户在 sigaction
中安装了带有 SA_RESETHAND
标志的信号处理程序。
但是,有一种情况是内核确实将 SIGSEGV
的信号操作更改为默认值。假设,用户已经安装了信号处理程序,然后在生成信号之前耗尽了整个内存。在这种情况下,内核将无法创建帧来执行信号处理程序,因为没有剩余内存。感知到这种情况后,内核会执行以下操作:
- 检查用户是否为
SIGSEGV
安装了处理程序。如果是,则将操作更改为默认也取消阻止 SIGSEGV
如果用户已阻止它。
- 向用户发送
SIGSEGV
信号以终止用户进程。
如果我为 SIGSEGV
设置了信号处理程序,则会生成如下分段错误:
int *a = NULL;
*a = 1;
将调用处理程序,但此信号处理程序只会调用一次。所以,我猜 Linux 内核会将信号处理程序重置为 SIG_DFL
,但是什么时候?我想知道细节,所以我查看了Linux内核源代码,但还没有找到线索。如果您知道详细信息,请告诉我代码。
这取决于您如何注册信号处理程序。
使用 sigaction
而没有 SA_RESETHAND
标志,将不会重置为 SIG_DFL
(尽管从信号处理程序 运行 返回以响应 SIGSEGV
交付到期到分段错误在技术上是 UB)。
使用 SA_RESETHAND
它将被重置,如果您使用 signal
注册处理程序,则未指定是否重置处理程序(因此不要使用 signal()
)。
示例:
#include <signal.h>
#include <unistd.h>
int volatile*a;
void h(int Sig) { write(1,"h\n", 2); }
int main()
{
//sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h}, 0); //won't reset the handler, will likely loop
sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h,.sa_flags=SA_RESETHAND}, 0); //will reset the handler
//signal(SIGSEGV,h); //may or may not reset the handler
*a=1;
return 0;
}
正如@PSkocik 正确回答的那样,在正常情况下,内核不会费心将信号操作更改为默认值,除非用户在 sigaction
中安装了带有 SA_RESETHAND
标志的信号处理程序。
但是,有一种情况是内核确实将 SIGSEGV
的信号操作更改为默认值。假设,用户已经安装了信号处理程序,然后在生成信号之前耗尽了整个内存。在这种情况下,内核将无法创建帧来执行信号处理程序,因为没有剩余内存。感知到这种情况后,内核会执行以下操作:
- 检查用户是否为
SIGSEGV
安装了处理程序。如果是,则将操作更改为默认也取消阻止SIGSEGV
如果用户已阻止它。 - 向用户发送
SIGSEGV
信号以终止用户进程。