gpt4 book ai didi

c - 信号不会在 execv() 中正确重新启用

转载 作者:IT王子 更新时间:2023-10-29 00:57:07 26 4
gpt4 key购买 nike

我正在为我正在开发的 Linux 发行版编写系统关键程序。它需要在接收到某些信号时自行重启,以避免崩溃。问题是,重启后,我无法重新启用该信号。也就是说,信号不能被接收到两次。在 execv() 自身之后,当新进程调用 signal() 来设置信号时,将返回 SIG_DFL。每次。即使我连续两次调用它 - 表明它从未在一开始就设置过。是否从原始过程中继承了一些奇怪的标志?

最佳答案

您实际上是在尝试递归处理信号,这与您犯规了。

使用 signal() 时要注册一个信号处理程序,该信号编号将被阻塞,直到信号处理程序返回 - 实际上内核/libc 在调用信号处理程序时阻塞该信号编号,并在信号处理程序返回后解除阻塞。因为你永远不会从信号处理程序返回(而不是你 execl 一个新的二进制文件),SIGUSR1保持阻塞状态,因此不会被第二次捕获。

这可以通过检查 /proc/</pid>/status 看出在发送第一个 SIGUSR1 之前和之后.

之前:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200

之后:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000200
SigCgt: 0000000000000200

请注意 SigCgt表示信号 10 已注册(数字是一个位域;第 10 位已设置,相当于 SIGUSR1,请参阅 man signal(7) 了解数字)。 SigBlk SIGUSR 之前为空被发送到您的进程,但在发送信号后它包含 SIGUSR1 .

解决这个问题有两种方法:

一个)。手动解锁SIGUSR打电话前execlsighandler :

sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);

b).使用 sigactionSA_NODEFER标记而不是 signal注册信号处理程序。这将防止 SIGUSR1在信号处理程序中被阻止:

struct sigaction act;
act.sa_handler = signalhandler;
act.sa_mask = 0;
act.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &act, 0);

关于c - 信号不会在 execv() 中正确重新启用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1023955/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com