执行默认信号处理程序

发布于 2024-11-07 15:14:08 字数 501 浏览 6 评论 0原文

我编写了一个应用程序,其中我为 linux 中的不同信号注册了多个信号处理程序。 进程接收到信号后,控制权将转移到我注册的信号处理程序。在这个信号处理程序中,我做了一些我需要做的工作,然后我想调用默认信号处理程序,即 SIF_DFLSIG_IGN 。 然而,SIG_DFLSIG_ING都是宏,分别扩展为数值0和1,这是无效的函数地址。

有什么方法可以调用默认操作,即 SIG_DFLSIG_IGN 吗?

为了达到 SIG_DFLSIG_ING 的效果,我分别调用 exit(1) 和不执行任何操作。但对于像 SIGSEGV 这样的信号,我也希望有核心转储。 一般来说,我希望我的默认行为与 SIG_DFL 相同,并忽略相同 SIG_IGN 的行为,就像操作系统所做的那样。

I have written an application where i have registered number of signal handler for different signals in linux .
After process receives the signal the control is transferred to the signal handler i had registered. In this signal handler i do some work which i need to do, and then i would like to call the default signal hander i.e SIF_DFL or SIG_IGN .
However, SIG_DFL and SIG_ING are both macros which expand to numeric values 0 and 1 respectively, which are invalid function addresses.

IS there any way i can call default actions i.e SIG_DFL or SIG_IGN ?

In order to achieve the effect of SIG_DFL or SIG_ING i call exit(1) and do nothing , respectively . But for signals like SIGSEGV i also would like to have core dump .
In general i would want to my default behavior to be same as SIG_DFL and ignore behavior same SIG_IGN , the way Operating system would do .

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

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

发布评论

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

评论(4

浅唱ヾ落雨殇 2024-11-14 15:14:08

GNU C 库参考手册有一整章解释关于信号处理的一切。

当您安装自己的处理程序时,您始终会获得先前设置的信号处理程序(函数指针)(请参阅 signal()sigaction() 的联机帮助页)。

previous_handler = signal(SIGINT, myhandler);

一般规则是,您始终可以重置到前一个处理程序并再次 raise() 信号。

void myhandler(int sig) {
  /* own stuff .. */
  signal(sig, previous_handler);
  raise(sig);
  /* when it returns here .. set our signal handler again */
  signal(sig, myhandler);
}

一般规则有一个缺点:映射到信号的硬件异常通常被分配给导致异常的特定指令。因此,当您再次发出信号时,相关指令与原来的指令不同。这可能但不应该损害其他信号处理程序。

另一个缺点是,每个升高的信号都会导致大量的处理时间。为了防止过度使用 raise(),您可以使用以下替代方法:

  1. 如果是 SIG_DFL,函数指针指向地址 0 (这显然不是有效地址)。因此,您必须重置处理程序并再次raise()信号。

    if (previous_handler == SIG_DFL)
    {
      信号(sig,SIG_DFL);
      提高(签名);
      信号(sig,我的处理程序);
    } 
  2. SIG_IGN 的值为 1(也是一个无效地址)。在这里你可以直接返回(什么也不做)。

    else if (previous_handler == SIG_IGN)
    {
      返回;
    } 
  3. 否则(SIG_IGNSIG_DFL)您已收到有效的函数指针,并且您可以直接调用处理程序,

    <前><代码>其他
    {
    先前的处理程序(sig);
    }

您还必须考虑不同的 API(请参阅 signal()sigaction() 的联机帮助页)。

The GNU C Library Reference Manual has a whole chapter explaining everything about signal handling.

You always get the previously set signal handler (a function pointer) when you install your own handler (see manpages for signal() or sigaction()).

previous_handler = signal(SIGINT, myhandler);

The general rule is, that you can always reset to the previous handler and raise() the signal again.

void myhandler(int sig) {
  /* own stuff .. */
  signal(sig, previous_handler);
  raise(sig);
  /* when it returns here .. set our signal handler again */
  signal(sig, myhandler);
}

There is one disadvantage of the general rule: Hardware exceptions which are mapped to signals are usually assigned to a certain instruction which caused the exception. So, when you raise a signal again, the associated instruction is not the same as originally. This can but should not harm other signal handlers.

Another disadvantage is, that each raised signal causes a lot of processing time. To prevent excessive use of raise() you can use the following alternatives:

  1. In case of SIG_DFL the function pointer points to address 0 (which is obviously no valid address). Thus, you have to reset the handler and raise() the signal again.

    if (previous_handler == SIG_DFL)
    {
      signal(sig, SIG_DFL);
      raise(sig);
      signal(sig, myhandler);
    } 
  2. SIG_IGN has value 1 (also an invalid address). Here you can just return (do nothing).

    else if (previous_handler == SIG_IGN)
    {
      return;
    } 
  3. Otherwise (neither SIG_IGN nor SIG_DFL) you have received a valid function pointer and you can call the handler directly,

    else
    {
      previous_handler(sig);
    }

Of course, you have to consider the different APIs as well (see manpages for signal() and sigaction()).

偏爱你一生 2024-11-14 15:14:08

您可以保存之前的处理程序,然后在适当的时候调用它。

安装处理程序。确保保存旧处理程序

static struct sigaction new_sa, old_sa;

new_sa.sa_handler = my_handler;
sigemptyset(&new_handler.sa_mask);

if (sigaction(signo, &new_sa, &old_sa) == -1) {
    /* handle sigaction error */
}

在新处理程序中,调用旧处理程序

(*old_sa.sa_handler)(signo)

您不需要再次引发它或做任何混乱的事情;只需调用旧的处理程序(当然,由于您保存了sigaction,因此您可以访问旧的配置等等)。

You can save the previous handler and then call it when the time is right.

Install handler. Make sure you save old handler

static struct sigaction new_sa, old_sa;

new_sa.sa_handler = my_handler;
sigemptyset(&new_handler.sa_mask);

if (sigaction(signo, &new_sa, &old_sa) == -1) {
    /* handle sigaction error */
}

In your new handler, call the old handler

(*old_sa.sa_handler)(signo)

You don't need to raise it again or do any messy stuff; simply call the old handler (of course, since you saved the sigaction you have acces to the old disposition and so on).

金兰素衣 2024-11-14 15:14:08

通常的方法是重置信号处理程序,然后再次 raise() 信号:

下面是一个 SIGINT 处理程序示例:

void sigint_handler(int num)
{
    /* handle SIGINT */

    // call default handler
    signal(SIGINT, SIG_DFL);
    raise(SIGINT);
}

The usual approach is to reset the signal handler and then raise() the signal again:

Here's an example SIGINT handler:

void sigint_handler(int num)
{
    /* handle SIGINT */

    // call default handler
    signal(SIGINT, SIG_DFL);
    raise(SIGINT);
}
瞳孔里扚悲伤 2024-11-14 15:14:08

鉴于信号处理程序是在内核中实现的,我看到的唯一方法是

  • 重置处理程序并
  • 再次 raise() 信号

Given the signal handlers are implemented in kernel, the only way I see is to

  • reset the handler and
  • raise() the signal again
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文