关于system()实现中阻塞sigchld信号的问题(转帖)

1813阅读 0评论2012-01-03 suanmeilizhi
分类:

这是一个网友的提问:

在 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()中的出现。
上一篇:gdb解决段错误实践
下一篇:GDB调试技巧:调试复杂的宏定义