如何向标准信号处理程序添加代码?

发布于 2024-12-04 07:14:48 字数 195 浏览 1 评论 0原文

我有一个在 Linux 上运行的 C 应用程序,我需要向标准信号处理程序添加一些代码。我的想法是设置我的处理程序,将指针保存到标准处理程序,并从我的代码中调用保存的处理程序。不幸的是,signal() 和 sigaction() 都没有返回指向标准处理程序的指针。它们都返回 NULL。 有没有办法进行自定义处理并继续标准处理,而无需删除自定义处理程序并再次发送相同的信号?

I have a C application running on Linux where I need to add some code to the standard signal handler. The idea was to setup my handler saving the pointer to the standard one and call the saved handler from my code. Unfortunately, neither signal() nor sigaction() return pointer to the standard handler. Both of them return NULL instead.
Is there any way of doing custom handling and continuing with the standard handling without removal of the custom handler and sending the same signal again?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只有影子陪我不离不弃 2024-12-11 07:14:48

不存在“标准信号处理程序”;相反,当信号未被处理时,内核会执行默认操作。如果您想在收到信号时执行某些操作,则遵循默认操作,您可以在信号处理程序末尾执行以下操作:

sigset_t set;
signal(sig, SIG_DFL);
raise(sig);
sigemptyset(&set);
sigaddset(&set, sig);
sigprocmask(SIG_UNBLOCK, &set, 0);

假设您使用 sigaction 安装信号处理程序,并且未指定 SA_NODEFERSA_RESETHAND 标志。使用这些标志并简单地调用 raise 也可以实现您想要的目的,但是如果信号快速连续传递两次,这会产生丑陋的竞争条件,因此您不应该这样做;而是使用我建议的方法。

编辑:实际上,您不必执行任何信号掩码操作,因为从信号处理程序返回将恢复旧的信号掩码。这应该有效:

signal(sig, SIG_DFL);
raise(sig);
return;

There is no "standard signal handler"; instead, there's a default action performed by the kernel when a signal is unhandled. If you want to do something when the signal is received, then defer to the default action, you can do the following at the end of your signal handler:

sigset_t set;
signal(sig, SIG_DFL);
raise(sig);
sigemptyset(&set);
sigaddset(&set, sig);
sigprocmask(SIG_UNBLOCK, &set, 0);

This is assuming you used sigaction to install your signal handler, and did not specify the SA_NODEFER or SA_RESETHAND flags. It's also possible to achieve what you want using those flags and simply calling raise, but this has ugly race conditions if the signal is delivered twice in rapid succession, so you should not do it; instead use the method I suggested.

Edit: Actually you don't have to do any of the signal mask stuff, since returning from the signal handler will restore the old signal mask. Just this should work:

signal(sig, SIG_DFL);
raise(sig);
return;
酷遇一生 2024-12-11 07:14:48

当调用 signal() 或 sigaction() 返回 NULL 时,意味着 SIG_DFL (即默认信号处理程序)

如果您使用 signal(),则处理程序应该在调用处理程序时重置,您可以发出 raise(信号)作为
信号处理程序中的最后一行,它应该调用默认处理程序。

如果您使用 sigaction() 那么您应该传入 SA_RESETHAND 作为标志之一,这将允许您在该处理程序中使用 raise(SIGNAL) 调用。

绝大多数默认信号处理程序将终止应用程序,因此这种“一次性”替换将起作用。您可以添加
在 raise 调用之后调用 sigaction() 来再次存储新的处理程序,例如

void sighandler(int signum)
{
    // Do my stuff
    raise(signup);
    signal(signum, sighandler);
}

When the call to signal() or sigaction() returns NULL, it implies SIG_DFL (i.e. default signal handler)

If you're using signal(), the handler is supposed to be reset when the handler is called, you can issue raise(SIGNAL) as
the last line in the signal handler and it should invoke the default handler.

If you're using sigaction() then you should pass in SA_RESETHAND as one of the flags, which will allow you to use the raise(SIGNAL) call in that handler.

The vast majority of default signal handlers will terminate the application, so this 'one shot' replacement will work. You can add
a sigaction() call after the raise call to store the new handler again e.g.

void sighandler(int signum)
{
    // Do my stuff
    raise(signup);
    signal(signum, sighandler);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文