您的位置:首页 > 其它

处理多个信号时产生的问题

2014-04-30 18:22 134 查看
#include<stdio.h>

#include<errno.h>

#include<unistd.h>

#include<signal.h>

#include<sys/types.h>

void handler( int sig )

{

pid_t pid;

if( (pid=waitpid(-1, NULL, 0))
< 0 )

perror( "waitpid error" );

printf(
"handler reaped child %d\n", (int)pid );

sleep( 2
);

return;

}

int main( int argc, char **argv )

{

int
i,n;

char
buf[20];

if(
signal(SIGCHLD, handler) == SIG_ERR )

perror( "signal error" );

for( i = 0;
i < 3; i++ )

{

if( fork() == 0 )

{

printf( "hello from child %d\n", (int)getpid() );

sleep( 1 );

exit( 0 );

}

}

if(
(n=read(STDIN_FILENO, buf, sizeof(buf))) < 0 )

perror( "read" );

printf(
"parent processing input\n" );

while( 1
);

exit( 0
);

}

程序输出:

hello from child 3556

hello from child 3557

hello from child 3558

handler reaped child 3556

handler reaped child 3557

可见进程3558没有被回收。

原因:父进程创建了3个子进程,并等待其中子进程的终止信号。

父进程接收捕获了第一个SIGCHLD信号(进程3556的终止信号)。当处理程序还在处理第一个信号时,第二个SIGCHLD信号(进程3557的终止信号)就传送添加到了待处理信号集了,并等待前一个SIGCHLD处理程序的结束(也就是被前一个阻塞)。很快,当处理程序还在处理第一个信号时,第三个信号(进程3558终止信号)来了,由于任意类型至多只有一个待处理信号,所以信号3被丢弃。当第一个信号的处理程序返回后,内核执行第二个信号的处理程序。这样,第三个信号久丢失了。

修正方法:

改变信号处理程序:

void handler( int sig )

{

pid_t pid;

while( (pid=waitpid(-1, NULL,
0)) > 0 )

printf( "handler reaped child %d\n", (int)pid );

// perror( "waitpid error" );

sleep( 2
);

return;

}

输出:

hello from child 3551

hello from child 3552

hello from child 3553

handler reaped child 3551

handler reaped child 3552

handler reaped child 3553

改动原理:

存在一个待处理信号只是暗示自进程最后一次收到一个信号以来,至少已经有一个这种类型的信号被发送了。所以应该在每次信号处理函数被调用时,回收尽可能多的僵死进程。这样就不会发生上述情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: