if(!tsk->ptrace && sig == SIGCHLD && (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN|| (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))){ /* * We are exiting and our parent doesn't care. POSIX.1 * defines special semantics for setting SIGCHLD to SIG_IGN * or setting the SA_NOCLDWAIT flag: we should be reaped * automatically and not left for our parent's wait4 call. * Rather than having the parent do it as a magic kind of * signal handler, we just set this to tell do_exit that we * can be cleaned up without becoming a zombie. Note that * we still call __wake_up_parent in this case, because a * blocked sys_wait4 might now return -ECHILD. * * Whether we send SIGCHLD or not for SA_NOCLDWAIT * is implementation-defined: we do (if you don't want * it, just use SIG_IGN instead). */ tsk->exit_signal =-1; if(psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) sig = 0; } if(valid_signal(sig)&& sig > 0) __group_send_sig_info(sig,&info, tsk->parent); __wake_up_parent(tsk, tsk->parent);
可见,如果SIGCHLD的signal handle function 设置为SIG_IGN或其sa_flags设置了SIG_NOCLDWAIT位,则子进程的退出不会generate a SIGCHLD signal,子进程结束的资源回收由子进程自行处理。其状态直接被设置为
TASK_DEAD,不经过TASK_ZOMBIE状态。
2.对于已经处于pending状态的信号
do_sigaction的注释中有这么一段:
/*
* POSIX 3.3.1.3:
* "Setting a signal action to SIG_IGN for a signal that is
* pending shall cause the pending signal to be discarded,
* whether or not it is blocked."
*
* "Setting a signal action to SIG_DFL for a signal that is
* pending and whose default action is to ignore the signal
* (for example, SIGCHLD), shall cause the pending signal to
* be discarded, whether or not it is blocked"
*/
测试代码:
if(sigismember(&pendmask,SIGCHLD)) printf("sigchld is now pending\n"); signal(SIGCHLD,SIG_DFL); printf("Alter signal handler function\n"); sigpending(&pendmask); if(!sigismember(&pendmask,SIGCHLD)) printf("now sigchld is not pending\n"); exit(0); }