重置 Linux 中忽略信号的掩码
Reset mask of ignored signal in Linux
在 exec()
期间,阻塞信号的掩码(由 sigprocmask()
设置)被 child 个进程继承。
但现在我注意到在Linux下,还有忽略信号的掩码(grep < /proc/self/status ^SigIgn
),它也被child进程继承。由于这些是由 sigaction()
和 act.sa_handler = SIG_IGN
设置的,我本以为,作为信号处理程序,它们会在执行期间被重置。但他们不是。
考虑下面的例子:parent 想要忽略 SIGINT,但它也扩展到 child,因此 sleep 120
不能被 kill -INT $(pidof sleep)
杀死不再。
问题:
这 POSIX 合规吗? sigaction() 的文档明确指出 sigaction
的效果不会在 exec
后继续存在(引述:“... 直到其中一个 exec 函数被调用”)。 Linux 手册页说“被忽略信号的配置保持不变”,我想这是一个 Linux 特定功能。
如何正确可靠地重置忽略掩码?我没有发现 sigprocmask()
的模拟 - 管理阻塞信号 - 来管理忽略信号的掩码。我应该简单地遍历所有信号并用 sigaction()
重置它们吗?
P.S。使用内核 v3.x 和 v4.9 进行测试,行为相同。
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
struct sigaction act;
sigset_t ss;
system("grep -n < /proc/self/status ^SigIgn");
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction( SIGINT, &act, NULL );
system("grep -n < /proc/self/status ^SigIgn");
sigemptyset(&ss);
sigprocmask(SIG_SETMASK, &ss, NULL);
system("grep -n < /proc/self/status ^SigIgn");
system("sleep 120");
return 0;
}
- Is this POSIX compliant?
是,https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html 指定:
Signals set to the default action (SIG_DFL) in the calling process
image shall be set to the default action in the new process image.
Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling
process image shall be set to be ignored by the new process image.
Signals set to be caught by the calling process image shall be set to
the default action in the new process image (see ).
(强调我的)
Blocked-信号掩码,默认-信号掩码,以及忽略-信号掩码都是在 POSIX 中的 exec*
调用中继承的,尽管 POSIX 并没有真正的后两个掩码的概念(它们只是特殊的信号配置,分别为每个信号设置,与可以整体修改的阻塞信号掩码不同)。
- How to reset the ignore mask correctly & reliably? I have found no
analog of sigprocmask() - manages blocked signals - to manage the mask
of ignored signals. Should I simply iterate over all signals and reset
them with sigaction()?
是——用 sigaction
或 signal
迭代信号。 (虽然 sigaction
应该是首选,但为了将信号设置为 SIG_IGN
/SIG_DFL
,信号足够、便携且更紧凑。)。理想情况下,这应该在 fork()
之后完成,以防止与其他线程竞争(信号处置是共享的全局状态)。
更好的是,您可以将 posix_spawn
/posix_spawnp
与一个属性 (posix_spawnattr_t
) 一起使用,该属性指定应在子进程中重置为默认值的一组信号。 posix_spawnattr_setsigdefault
属性-setter可以用来指定这个信号集。
在 exec()
期间,阻塞信号的掩码(由 sigprocmask()
设置)被 child 个进程继承。
但现在我注意到在Linux下,还有忽略信号的掩码(grep < /proc/self/status ^SigIgn
),它也被child进程继承。由于这些是由 sigaction()
和 act.sa_handler = SIG_IGN
设置的,我本以为,作为信号处理程序,它们会在执行期间被重置。但他们不是。
考虑下面的例子:parent 想要忽略 SIGINT,但它也扩展到 child,因此 sleep 120
不能被 kill -INT $(pidof sleep)
杀死不再。
问题:
这 POSIX 合规吗? sigaction() 的文档明确指出
sigaction
的效果不会在exec
后继续存在(引述:“... 直到其中一个 exec 函数被调用”)。 Linux 手册页说“被忽略信号的配置保持不变”,我想这是一个 Linux 特定功能。如何正确可靠地重置忽略掩码?我没有发现
sigprocmask()
的模拟 - 管理阻塞信号 - 来管理忽略信号的掩码。我应该简单地遍历所有信号并用sigaction()
重置它们吗?
P.S。使用内核 v3.x 和 v4.9 进行测试,行为相同。
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
struct sigaction act;
sigset_t ss;
system("grep -n < /proc/self/status ^SigIgn");
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction( SIGINT, &act, NULL );
system("grep -n < /proc/self/status ^SigIgn");
sigemptyset(&ss);
sigprocmask(SIG_SETMASK, &ss, NULL);
system("grep -n < /proc/self/status ^SigIgn");
system("sleep 120");
return 0;
}
- Is this POSIX compliant?
是,https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html 指定:
Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see ).
(强调我的)
Blocked-信号掩码,默认-信号掩码,以及忽略-信号掩码都是在 POSIX 中的 exec*
调用中继承的,尽管 POSIX 并没有真正的后两个掩码的概念(它们只是特殊的信号配置,分别为每个信号设置,与可以整体修改的阻塞信号掩码不同)。
- How to reset the ignore mask correctly & reliably? I have found no analog of sigprocmask() - manages blocked signals - to manage the mask of ignored signals. Should I simply iterate over all signals and reset them with sigaction()?
是——用 sigaction
或 signal
迭代信号。 (虽然 sigaction
应该是首选,但为了将信号设置为 SIG_IGN
/SIG_DFL
,信号足够、便携且更紧凑。)。理想情况下,这应该在 fork()
之后完成,以防止与其他线程竞争(信号处置是共享的全局状态)。
更好的是,您可以将 posix_spawn
/posix_spawnp
与一个属性 (posix_spawnattr_t
) 一起使用,该属性指定应在子进程中重置为默认值的一组信号。 posix_spawnattr_setsigdefault
属性-setter可以用来指定这个信号集。