gpt4 book ai didi

c - 为什么sigprocmask用于阻止SIGCHLD在以下代码中传递

转载 作者:IT王子 更新时间:2023-10-29 00:47:07 25 4
gpt4 key购买 nike

基于http://man7.org/tlpi/code/online/book/procexec/multi_SIGCHLD.c.html

int
main(int argc, char *argv[])
{
int j, sigCnt;
sigset_t blockMask, emptyMask;
struct sigaction sa;

if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s child-sleep-time...\n", argv[0]);

setbuf(stdout, NULL); /* Disable buffering of stdout */

sigCnt = 0;
numLiveChildren = argc - 1;

sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sigchldHandler;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
errExit("sigaction");

/* Block SIGCHLD to prevent its delivery if a child terminates
before the parent commences the sigsuspend() loop below */

sigemptyset(&blockMask);
sigaddset(&blockMask, SIGCHLD);
if (sigprocmask(SIG_SETMASK, &blockMask, NULL) == -1)
errExit("sigprocmask");

for (j = 1; j < argc; j++) {
switch (fork()) {
case -1:
errExit("fork");

case 0: /* Child - sleeps and then exits */
sleep(getInt(argv[j], GN_NONNEG, "child-sleep-time"));
printf("%s Child %d (PID=%ld) exiting\n", currTime("%T"),
j, (long) getpid());
_exit(EXIT_SUCCESS);

default: /* Parent - loops to create next child */
break;
}
}

/* Parent comes here: wait for SIGCHLD until all children are dead */

sigemptyset(&emptyMask);
while (numLiveChildren > 0) {
if (sigsuspend(&emptyMask) == -1 && errno != EINTR)
errExit("sigsuspend");
sigCnt++;
}

printf("%s All %d children have terminated; SIGCHLD was caught "
"%d times\n", currTime("%T"), argc - 1, sigCnt);

exit(EXIT_SUCCESS);
}

这是我的理解:

sigprocmask(SIG_SETMASK, &blockMask, NULL)

调用进程的结果信号集应该是blockMask指向的信号集。

问题

为什么要说下面的说法呢?

Block SIGCHLD to prevent its delivery if a child terminates before the parent commences the sigsuspend() loop below

换句话说,根据sigprocmask语句的给定描述,我不明白为什么要使用sigprocmask来阻止SIGCHLD。

最佳答案

嗯,我觉得评论说的很清楚了...

每当您调用 fork() 并希望以任何方式与 child 互动时,都需要考虑竞争条件。如果 child 比 parent 先跑一段时间怎么办?还是相反?

在这种情况下,无法知道父级在调用 fork 之后需要多长时间才能到达对 sigsuspend 的调用。那么,如果 fork 子进程在父进程调用 sigsuspend 之前完成了它的 sleep 并调用了 exit 怎么办?然后父级将收到一个 SIGCHLD,它忽略了...然后它将调用 sigsuspend,它将永远不会返回,因为 SIGCHLD已经交付。

唯一 100% 的解决方案是在调用 fork 之前阻止 SIGCHLD ,然后在 sigsuspend< 入口处自动取消阻止它。 (处理这种竞争条件正是 sigsuspend 需要信号掩码作为参数的原因...如果您在调用 sigsuspend 之前尝试解除信号阻塞,就会出现竞争条件;即信号可能在您开始等待之前传递。更改信号掩码然后进入等待必须是原子的,并且您必须在可能生成之前阻止您想要等待的任何信号。)

关于c - 为什么sigprocmask用于阻止SIGCHLD在以下代码中传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6757188/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com