c - 为什么不处理 SIGUSR1 信号?

标签 c

我正在编写一个 Unix 程序,其中一个父进程派生一个子进程,稍后它必须发送一个 SIGUSR1 信号由 handler_sigusr1 处理,并发送一个 SIGKILL 信号来完成该程序。 我的问题是,当我运行该程序时,子程序应该收到 SIGUSR1,然后收到 SIGKILL,但它只收到 SIGKILL。 我的代码有问题吗?感谢您的帮助!

void handler_sigusr1()
{
    printf("Signal SIGUSR1\n");
}

int main(int argc, char **argv)
{
    struct sigaction action;
    sigset_t new_mask, oldmask;
    int status;

    action.sa_flags = 0;

    sigaction(SIGTERM, &action, NULL);
    sigemptyset(&new_mask);
    sigaddset(&new_mask, SIGTERM);

    sigaction(SIGUSR1, &action, NULL);
    action.sa_handler = handler_sigusr1;
    sigaddset(&new_mask, SIGUSR1);

    child1 = fork();
    if(child1 == 0)
    {
        sigprocmask(SIG_BLOCK, &new_mask, &oldmask);
        sigsuspend(&new_mask);
    }
    if(child1 != 0)
    {
        kill(child1, SIGUSR1);
        kill(child1, SIGKILL);
    }
    wait(&status);
}

最佳答案

有4个问题:

问题 1

设置信号处理程序的代码是错误的。

这两行顺序错误:

    sigaction(SIGUSR1, &action, NULL);
    action.sa_handler = handler_sigusr1;

应该是

    action.sa_handler = handler_sigusr1;
    sigaction(SIGUSR1, &action, NULL);

第 2 期

您的父进程在发送 SIGUSR1 后立即向您的子进程发送 SIGKILL。 SIGKILL 将终止您的子进程 - 它不能被阻止或忽略。

除非你很幸运,否则你的 child 的 sigusr1 处理程序将无法在父进程发送 SIGKILL 之前运行或完成 - 这会立即终止子进程。

您可以通过像这样插入延迟来大大增加 SIGUSR1 被传递和处理的机会:

kill(child1, SIGUSR1);
sleep(1);
kill(child1, SIGKILL);

问题 3

您已阻止 SIGUSR1,因此它不会传送到您的进程。

删除行

 sigaddset(&new_mask, SIGUSR1);

请注意,当使用 sigprocmask()sigsuspend() 设置信号掩码时,掩码中设置的信号是被阻塞的信号.

第四期

您不能在信号处理程序中安全地使用 printf()。

printf() 不是信号异步安全的,不能在信号处理程序中使用。如果你不走运,它可能不会像在信号处理程序中使用时那样表现。使用 write() 而不是直接写入标准输出,例如

 write(1, "Signal SIGUSR1\n", 15);

关于c - 为什么不处理 SIGUSR1 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40984985/

相关文章:

c - C++ 注释在 C 中被认为是糟糕的风格吗?

c - 类型转换的段错误

c++ - 在 Windows 内核设备驱动程序中使用 fprintf

c - 这个 __VA_ARGS__ 扩展有效 c99 吗?

c - 从表示为 char[] 的街道地址解析门牌号

c - 段错误 fgets() 两遍汇编器

c - 对 sqlite_open 的 undefined reference

c++ - c++ (Direct2D) 中的混合模式

c - 如何从单独的函数解析命令行参数

c - 汇编到 C 矩阵协助