gpt4 book ai didi

linux - 在 Linux 上显式调用 SIG_DFL/SIG_IGN 处理程序

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:44 26 4
gpt4 key购买 nike

我已经阻塞,然后通过以下代码等待信号:

sigset_t set;
sigfillset(&set); // all signals
sigprocmask(SIG_SETMASK, &set, NULL); // block all signals
siginfo_t info;
int signum = sigwaitinfo(&set, &info); // wait for next signal
struct sigaction act;
sigaction(signum, NULL, &act); // get the current handler for the signal
act.sa_handler(signum); // invoke it

最后一行生成段错误,因为处理程序设置为 SIG_DFL(定义为 0)。如果设置为 SIG_DFLSIG_IGN,我如何手动调用默认处理程序?另请注意,SIG_IGN 定义为 1

最佳答案

如您所见,您无法调用 SIG_DFL 和 SIG_IGN 本身。但是,您可以或多或少地模仿他们的行为。

简单地说,模仿正常的信号处理是:

  • 对于用户定义的 sa_handler 来说非常容易
  • 对于 SIG_IGN 来说足够简单,但需要注意的是在 CHLD 的情况下您需要 waitpid()
  • 对于 SIG_DFL 来说直截了当但令人不快,重新加注以让内核发挥其魔力。

这是否符合您的要求?

#include <signal.h>
#include <stdlib.h>

/* Manually dispose of a signal, mimicking the behavior of current
* signal dispositions as best we can. We won't cause EINTR, for
* instance.
*
* FIXME: save and restore errno around the SIG_DFL logic and
* SIG_IGN/CHLD logic.
*/
void dispatch_signal(const int signo) {
int stop = 0;
sigset_t oset;
struct sigaction curact;

sigaction(signo, NULL, &curact);

/* SIG_IGN => noop or soak up child term/stop signals (for CHLD) */
if (SIG_IGN == curact.sa_handler) {
if (SIGCHLD == signo) {
int status;
while (waitpid(-1, &status, WNOHANG|WUNTRACED) > 0) {;}
}
return;
}

/* user defined => invoke it */
if (SIG_DFL != curact.sa_handler) {
curact.sa_handler(signo);
return;
}

/* SIG_DFL => let kernel handle it (mostly).
*
* We handle noop signals ourselves -- "Ign" and "Cont", which we
* can never intercept while stopped.
*/
if (SIGURG == signo || SIGWINCH == signo || SIGCONT == signo) return;

/* Unblock CONT if this is a "Stop" signal, so that we may later be
* woken up.
*/
stop = (SIGTSTP == signo || SIGTTIN == signo || SIGTTOU == signo);
if (stop) {
sigset_t sig_cont;

sigemptyset(&sig_cont);
sigaddset(&sig_cont, SIGCONT);
sigprocmask(SIG_UNBLOCK, &sig_cont, &oset);
}

/* Re-raise, letting the kernel do the work:
* - Set exit codes and corefiles for "Term" and "Core"
* - Halt us and signal WUNTRACED'ing parents for "Stop"
* - Do the right thing if we forgot to handle any special
* signals or signals yet to be introduced
*/
kill(getpid(), signo);

/* Re-block CONT, if needed */
if (stop) sigprocmask(SIG_SETMASK, &oset, NULL);
}

更新(回应OP的优秀问题)

1: does this slot in after the sigwaitinfo?

是的。像这样的东西:

... block signals ...
signo = sigwaitinfo(&set, &info);
dispatch_signal(signo);

2: Why not raise those signals handled by SIG_IGN, they'll be ignored anyway

在用户空间中执行 noop 比通过三个系统调用(重新引发、取消屏蔽、重新屏蔽)稍微高效一些。此外,当 SIG_IGNored 时,CHLD 具有特殊的语义。

3: Why treat SIGCHLD specially?

最初(检查答案编辑)我没有——在 SIG_IGN 案例中重新提出它,因为IGNored CHLD signals tell the kernel to automatically reap children .

但是,我更改了它,因为"natural" CHLD signals carry information aboutthe terminated process (至少 PID、状态和真实 UID)。用户生成的 CHLD 信号不具有相同的语义,并且在我的测试中,忽略它们不会导致 2.6 自动获取 SIGCHLD 排队的僵尸被“错过”了。所以,我自己做。

4: Why are "stop" related signals unblocking CONT. Will not invoking the default handler for CONT unstop the process?

如果我们停止(不执行)并且 CONT 被阻塞,我们将永远不会收到叫醒我们的信号!

5: Why not call raise instead of the kill line you've given?

个人喜好; raise() 也可以。

关于linux - 在 Linux 上显式调用 SIG_DFL/SIG_IGN 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3147840/

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