这是一个网友的提问:
在
UNIX的system()函数实现过程中,要求在父进程中忽略掉SIGINT和SIGQUIT信号,但是要将SIGCHLD信号阻塞(在子进程中将
SIGINT和SIGQUIT信号设为默认,SIGCHLD信号解锁)。子进程执行完毕后,在父进程中调用waitpid(pid_t,
&state, 0)。问题:
1、若父进程已被waitpid阻塞,在子进程返回时,此时在父进程中SIGCHLD被阻塞(BLOCK),父进程收不到SIGCHLD信号,waitpid()函数能否正确返回,收集到子进程的信息?
2、
waitpid若能正确完成,在以后父进程中,将SIGCHLD信号UNBLOCK,用sigprocmask()函数解锁,书上说,在
sigprocmask()函数返回以前,会将以前阻塞的信号发送给进程,父进程是否还能收到SIGCHLD信号?若能收到何必在开始时将SIGCHLD
进程阻塞。
简单的对这个问题的解释是wait及其变体并不是通过sigchld信号来知道子进程状态的。
sigprocmask
阻塞的是有signal或sigaction设置的信号处理程序,即带有SIGCHLD_Handle()等处理函数。wait不是靠接收sigchld
信号获得子进程的退出状态的,如果进程中同时设置了signal和wait,则子进程退出后发出sigchld信号,交到signal的信号处理程序处
理,wait接收到子进程退出状态。
只是接收sigchld,而不调用wait还是会使子进程僵死的。一般的只有调用wait才能使子进程不成为僵死进程(除了2次fork 等或其他一些手段)。
概括下:waitpid不是依靠SIGCHLD是否到达来判断子进程是否退出,但是如果设置了SIGCHLD的处理函数,那么就需要等待SIGCHLD信号
的发生并完成信号处理函数,waitpid才能接收到子进程的退出状态。在APUE中的system()实现中阻塞了SIGCHLD信号,但是并没有设置
信号处理函数,所以waitpid在阻塞了SIGCHLD的情况下依然能正常返回,因为SIGCHLD在未设置信号处理函数的情况下不会影响到
waitpid的工作。至于为什么要阻塞SIGCHLD信号呢?那就是为了防止其他程序(main除了会调用system还会使用其他程序)设置了
SIGCHLD的信号处理函数,如果其他程序设置了SIGCHLD信号处理函数,在waitpid等待子程序的返回前,要去处理SIGCHLD信号处理程
序,如果阻塞了该信号,就不会去处理该信号处理程序,防止多余信息在system()中的出现。