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

问题描述 投票:2回答:1

考虑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...

显然,在子进程退出后,父进程的sigsuspend调用(pid 6024)立即返回。尽管SIGINT似乎没有被触发,但是sigsuspend返回errnoEINTR,即,报告通过非屏蔽信号之一成功终止。请注意,如果我阻止子进程退出,则sigsuspend会自动返回[[not,而是等待SIGINT传递。

我使用API​​的方式是否有问题?还是在POSIX规范中某种程度的灵活性使这两种行为都可以预期?]
c unix fork posix
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.