1.SIGCHLD简介
SIGCHILD是指在一个进程终止或者停止时,将SIGCHILD信号发送给其父进程,按照系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。注意:SIGCLD信号与其长得非常相似。SIGCLD是系统V的一个信号名,其语义与名为SIGCHLD的BSD信号不同。POSIX.1则采用BSD的SIGCHLD信号。BSD的SIGCHLD信号语义与其他信号的语义想类似。子信号状态改变后产生此信号,父进程需要调用一个wait函数以确定发生什么。
2.SIGCHLD发生的条件
1.子进程已终止 CLD_EXITED
2.子进程异常终止(无core) CLD_KILLED
3.子进程异常终止(有core) CLD_DUMPED
4.被跟踪子进程以陷入 CLD_TRAPPED
5.子进程已停止 CLD_STOPED
6.停止的子进程已经继续 CLD_CONTINUED
7.子进程处在停止态,接受到SIGCONT后唤醒时
3.SIGCHLD注意事项
- 当阻塞于某个慢系统调用的一个进程捕获某个信号且响应信号处理函数返回时,该系统调用可能返回EINTR错误;
- 在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程。按系统默认将忽略此信号。如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。信号的捕捉函数中通常调用wait函数以取得进程ID和其终止状态。
- SIGCHLD的信号处理函数必须正确编写,应使用waitpid函数来避免留下僵尸进程。
// 信号处理函数
void sig_handler(int signo)
{pid_t fpid = 0;std::vector< int > fpids;if(SIGCHLD == signo) {//如果一个进程中有多个子进程在执行,那么wait函数将阻塞到第一个子进程终止时为止。//如果有多个子进程终止而成为僵尸进程,那么wait只能处理一个。也就是说,信号处理函数没能完全处理僵尸进程。while((fpid = waitpid(-1, NULL, WNOHANG)) > 0){fpids.push_back(fpid);}}if(master::instance()->reload_child(fpids) != error_ok) {log_error("reload child fail\n");}
}
参考:https://blog.csdn.net/u012877472/article/details/50165083
https://blog.csdn.net/oguro/article/details/53857376