关于SIGCHLD的几点讨论

http://blog.chinaunix.net/uid-130624-id-2907711.html

关于SIG_CHLD信号传递机制,从内核角度做些分析:
1.child退出,调用do_exit()
do_exit()->exit_notify->do_notify_parent

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"
*/
测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int
main(void)
{
sigset_t mask,pendmask;
pid_t pid;
sigemptyset(&mask);
sigaddset(&mask,SIGCHLD);
if(sigprocmask(SIG_BLOCK,&mask,NULL) < 0){
perror("sigprocmask error");
exit(1);
}

if((pid = fork()) == 0){
printf("child exit\n");
exit(0);
}

sleep(1);
if(sigpending(&pendmask) < 0){
perror("sigpending error");
exit(1);
}

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);
}

i运行结果:

$ ./a.out

child exit

sigchld is now pending

Alter signal handler function

now sigchld is not pending

可见sigaction的使用将SIGCHLD从pending queue中去掉。无论是tg的shared pending,还是thread group中各thread的private pending list.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值