【问题标题】:Using a sigaction handler with sigaction when SA_SIGINFO is not set未设置 SA_SIGINFO 时使用带有 sigaction 的 sigaction 处理程序
【发布时间】:2021-04-26 13:17:53
【问题描述】:

spec 这么说

如果在 sa_flags 中指定了 SA_SIGINFO,则 sa_sigaction (而不是 sa_handler)指定信号处理函数 签名。

但是,下面的代码可以神奇地工作

#include <stdio.h>
#include <signal.h>

static void handler(int signo, siginfo_t *si, void *uc){
   printf("si = %d\n", *(char*)si);
   printf("uc = %d\n", *(char*)uc);
}

int main(void)
{
      struct sigaction psa;
      psa.sa_flags = 0;
      psa.sa_sigaction = handler;
      sigaction(SIGTSTP, &psa, NULL);
      for(;;) {}
      return 0;
}

handler 能够访问 si 和 ui 处的内存,gdb 显示至少 si 确实是指向 siginfo_t 的指针。但是,code 将 sa_sigaction 和 sa_handler 实现为联合。如果运行时使用 sa_flags 来决定使用 sa_sigaction 还是 sa_handler,似乎很难知道应该使用 sa_sigaction...

这是否意味着运行时总是为这两种调用提供 si 和 uc ?这样的用户代码是否定义明确?

【问题讨论】:

  • 不管[它正在做什么,根据您的测试结果],传递额外参数的代码更少。它不会“伤害”sa_handler [你总是可以传递比签名指定更多的参数,第一个参数是int] 这有点争议。您的代码正在设置 wrong 结构成员,并且由于联合而“逍遥法外”。如果你真的需要知道,请拉 [linux] 内核源代码并追踪设置它的代码。这是 linux,但在另一个 posix sys 上,这可能不起作用(即不是联合)。
  • 它没有说明如果代码不这样做会是什么行为。所以这是一个经典的未定义行为。如果您编写这样的代码,请准备好在某些时候中断。
  • 顺便说一句,printf -> malloc -> 不是信号安全

标签: c linux unix signals


【解决方案1】:

这是否意味着运行时总是为这两种调用提供 si 和 uc?

这意味着特定的实现可以,是的。

这样的用户代码定义好了吗?

不,这意味着它依赖于碰巧在一个特定平台上工作的未定义行为。

请注意,即使在您当前的平台上,此快捷方式也可能不适合您。您可以原谅您的运行时本身在siginfo_tucontext_t 参数中使用垃圾的捷径。毕竟,通过不省略 SA_SIGINFO,您告诉实现您不需要该信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-03
    相关资源
    最近更新 更多