考虑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
返回errno
的EINTR
,即,报告通过非屏蔽信号之一成功终止。请注意,如果我阻止子进程退出,则sigsuspend
会自动返回[[not,而是等待SIGINT
传递。