为什么在 SIGUSR1 循环的处理程序中调用 kill(getpid(), SIGUSR1)?

Why does calling kill(getpid(), SIGUSR1) inside handler for SIGUSR1 loop?

我试图通过这段代码了解幕后发生的事情。这是我正在参加的 OS 课程介绍的期末考试中提出的问题。据我了解,当从内核模式返回到用户模式时,系统会检查是否有任何未决信号(通过检查信号向量)并倾向于处理它们。因此,当来自 kill 系统调用的程序 returns 时,OS 发现 SIGUSR1 处于挂起状态并调用处理程序。按照这个逻辑,处理程序应该在无限循环中打印“stack”,但是当 运行 这段代码实际上在无限循环中打印“Whosebug”。为什么会这样? 提前致谢。

void handler(int signo) {
    printf("stack");
    kill(getpid(), SIGUSR1);
    printf("overflow\n");
}

int main() {
    struct sigaction act;
    act.sa_handler = &handler;
    sigaction(SIGUSR1, &act, NULL);
    kill(getpid(), SIGUSR1);
    return 0;
}

您实际上在这里有未定义的行为,因为您使用未完全初始化的 struct sigaction 对象调用 sigaction。因此,根据 sa_flagssa_mask 字段中的值,可能会发生各种不同的事情。

其中一些不会在信号处理程序 运行ning 时阻塞 SIGUSR1,这意味着新的信号处理程序将 运行 在第一次调用 kill 时立即(在第一个处理程序之前) returns 并弹出其栈帧)。所以你最终会在堆栈上得到许多递归 handler 堆栈帧(以及 'stack' 的输出)直到它溢出。

其他组合会阻止信号,因此它不会立即触发第二个信号处理程序。相反,信号将“挂起”,直到第一个信号处理程序 returns.