c - 为什么退出的子进程会导致父进程的 sigsuspend 调用在 macOS 上返回?

标签 c unix fork posix

考虑以下 POSIX 系统的 C 代码:

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

#define CONTINUE_SIGNAL SIGINT

void continue_handler(int sig, siginfo_t *info, void *context)
{
    printf("[P] Continuing process with pid = %d...\n", getpid());
}

int main(void)
{
    struct sigaction act;
    sigset_t mask;
    pid_t pid;

    // Block the CONTINUE_SIGNAL for now.
    sigemptyset(&mask);
    sigaddset(&mask, CONTINUE_SIGNAL);
    sigprocmask(SIG_BLOCK, &mask, NULL);

    if ((pid = fork()) == 0)  {
        printf("[C] This is the child (pid %d).\n", getpid());
        return 0;
    }

    printf("[P] Parent (pid %d) has spawned child (pid %d).\n", getpid(), pid);

    // Call the 'continue_handler' when CONTINUE_SIGNAL is received.
    act.sa_sigaction = continue_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(CONTINUE_SIGNAL, &act, NULL);
    printf("[P] Waiting for CONTINUE_SIGNAL...\n");

    // Block all signals except CONTINUE_SIGNAL and wait for it to occur.
    sigfillset(&mask);
    sigdelset(&mask, CONTINUE_SIGNAL);
    sigsuspend(&mask);
    printf("[P] Signal received. Exiting...\n");

    return 0;
}

请注意,我已删除所有错误检查,以便能够以更紧凑的形式表示它。但是,我已经验证了在以下两种情况下所有函数都成功返回。

在 Linux 系统上,代码完全符合我的预期:父进程生成一个子进程并等待 SIGINT,然后继续执行 continue_handler .

[P] Parent (pid 804) has spawned child (pid 805).
[P] Waiting for CONTINUE_SIGNAL...
[C] This is the child (pid 805).
  <press Ctrl+C>
[P] Continuing process with pid = 804...
[P] Signal received. Exiting...

然而,在 macOS 上,我获得了以下输出(没有任何交互):

[P] Parent (pid 6024) has spawned child (pid 6025).
[P] Waiting for CONTINUE_SIGNAL...
[C] This is the child (pid 6025).
[P] Signal received. Exiting...

很明显,父进程(pid 6024)的sigsuspend调用在子进程退出后立即返回。虽然SIGINT似乎没有被触发,但是sigsuspend返回一个EINTRerrno,即报告成功终止通过非屏蔽信号之一。请注意,如果我阻止子进程退出,sigsuspend 不会自行返回,而是等待 SIGINT 被传送。

我使用 API 的方式有问题吗?还是 POSIX 规范中可能存在某种程度的灵 active ,使得这两种行为都符合预期?

最佳答案

请阅读:signals in MAX OS X

尤其是语句:

To ignore the signal, func should be SIG_IGN. 

不知何故,我在你的代码中没有看到这一点。

关于c - 为什么退出的子进程会导致父进程的 sigsuspend 调用在 macOS 上返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62252854/

相关文章:

c - 为什么我的文件执行此 header 两次,即使在 C 中 fork 时有保护措施?

c - 在c中分配空间并连接到无符号字符数组

c - 如何在 Ctrl+D 后重新启动标准输入?

github - 如何通过查看 github 的网络图来选择要使用的正确分支/fork?

linux - 按名称查找文件夹然后复制文件

c - fork 子 "prints"重定向标准输出两次

c++ - 如何创建进程并让它们执行不同的分配任务,例如使用 fork 从文件读取或写入文件

c - 使用 clock() 测量执行时间

c - 动态内存分配的字符指针分析

java - 使用 Runtime.exec 将 CC 添加到 mailx 命令