当子进程终止时理解SIGCHLD

6
我无法理解以下程序的输出。我注意到在子进程返回后,父进程在wait()之前没有睡眠3秒钟。如果将SIGCHLD设置为默认处理程序,则会睡眠3秒钟,调用wait并按预期返回。这里到底发生了什么?
# include <unistd.h>
# include <sys/types.h>
# include <stdio.h>
# include <sys/wait.h>
# include <signal.h>

void handler(int sig) {
printf("Iam in handler ...\n");
}

main() {

int status;
pid_t pid;

struct sigaction act;
//act.sa_flags=SA_NOCLDSTOP;
act.sa_handler=handler;
sigaction(SIGCHLD,&act,NULL);

if(!fork()) {
printf("child process id is  %d\n",getpid());
 return 1;
}  

printf("xxx ...\n");
sleep(3);
pid = wait(&status);
printf("process terminated is %d\n",pid);

}

output::

xxx ...
child process id is  2445
Iam in handler ...
process terminated is 2445
2个回答

13

来自 sleep() 的说明

sleep() 让调用线程休眠,直到经过 seconds 秒或者接收到一个未被忽略的信号。

你的子进程终止会引起一个信号将你唤醒。

sleep() 的返回值:

如果经过了请求的时间,返回0,如果调用被信号处理程序中断,返回剩余的睡眠秒数。

可以用于帮助你“完成”睡眠。

unsigned sleep_time = 3;
...
while((sleep_time = sleep(sleep_time)) > 0) {}
pid = wait(&status);
...

9
当子进程死亡时,会向父进程发送一个SIGCHLD信号。在您的情况下,它会中断sleep,看起来好像进程没有睡眠。
问题的要点:当被信号中断时,sleep不会重新启动。

谢谢您的回答。我还有一个疑问——我从帖子中读到,系统调用的重新启动取决于其实现定义,并且一些系统调用根本不会重新启动。这是真的吗?重新启动系统调用是否与两次调用相同的调用相同? - Gowtam
@Goutham 这不是一样的。可以将其视为“尝试不返回EINTR的信号”。是的,信号重启大多取决于实现方式。 - cnicutar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接