- 论坛徽章:
- 0
|
有一个获取进程个数的程序:
sprintf(Cmd, "ps -ef|grep %s|grep %s|wc -l", prog, entr);
fp = popen(Cmd, "r");
if(fp == NULL) {
printf("打开管道[%s]错\n", Cmd);
return -1;
}
memset(buff, 0, sizeof(buff));
if ( fgets(buff, 256, fp) == NULL ) {
perror( "fgets:" );
printf("fgets() error[%d][%ld]\n",i, (long)getpid() );
pclose( fp );
return -1;
}
。。。。。。
pclose(fp);
正常运行是没有问题的。但是如果捕获了SIGCHLD信号后,重复执行以上程序,则会不定时在fgets()
时报错:Interrupted system call(errno==4)。
完整的程序代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<signal.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
struct sigaction sa_old;
struct sigaction sa_new;
/*------------------------------------------------------------------------
Function Name : agt_chld_exit
Description : 子进程结束信号处理
Input :
_sign 捕捉到的信号
Output :
Return :
------------------------------------------------------------------------*/
void agt_chld_exit(int _sign)
{
int e = errno;
int stat = 0;
pid_t pid_tmp = 0;
while((pid_tmp = waitpid(-1, &stat, WNOHANG)) > 0)
printf("进程[%d]退出\n", pid_tmp);
errno = e;
return;
}
int
main()
{
int i=0;
FILE *fp = NULL;
char Cmd[1025];
char buff[1025];
char prog[81];
char entr[9];
int Cnt = 0;
int ret = -1;
memset(&sa_old, 0, sizeof(sa_old));
memset(&sa_new, 0, sizeof(sa_new));
signal(SIGPIPE, SIG_IGN);
if(setpgrp() < 0) {
printf( "setpgrp error.\n");
exit(1);
}
signal(SIGPIPE, SIG_IGN);
ret = sigemptyset(&sa_new.sa_mask);
if(ret != 0) {
printf( "SIGEMPTYSET RET=[%d]\n", ret);
exit(1);
}
sa_new.sa_flags = 0;
sa_new.sa_handler = agt_chld_exit;
ret = sigaddset(&sa_new.sa_mask, SIGTERM);
if(ret != 0) {
printf( "SIGADDSET(SIGTERM) RET=[%d]\n", ret);
exit(1);
}
ret = sigaddset(&sa_new.sa_mask, SIGCHLD);
if(ret != 0) {
printf("SIGADDSET RET=[%d]\n", ret);
exit(1);
}
ret = sigaction(SIGTERM, &sa_new, &sa_old);
if(ret != 0) {
printf("SIGACTION RET=[%d]\n", ret);
exit(1);
}
ret = sigaction(SIGCHLD, &sa_new, &sa_old);
if(ret != 0) {
printf("SIGACTION RET=[%d]\n", ret);
exit(1);
}
memset(prog, 0, sizeof(prog));
memset(Cmd, 0, sizeof(Cmd));
memset(entr, 0, sizeof(entr));
strcpy(prog, "aa");
strcpy(entr, "bb");
while ( 1 ) {
sprintf(Cmd, "ps -ef|grep %s|grep %s|wc -l", prog, entr);
fp = popen(Cmd, "r");
if(fp == NULL) {
printf("打开管道[%s]错\n", Cmd);
return -1;
}
memset(buff, 0, sizeof(buff));
if ( fgets(buff, 256, fp) == NULL ) {
perror( "fgets:" );
printf("fgets() error[%d][%ld]\n",i, (long)getpid() );
pclose( fp );
return -1;
}
if ( strlen(buff) <= 0 ) {
printf("fgets() buff== NULL\n" );
pclose( fp );
return -1;
}
pclose(fp);
i++;
if ( i > 30000 )
break;
}
return 0;
}
如果不捕获SIGCHLD信号(把sigaction(SIGCHLD, &sa_new, &sa_old);那段屏蔽起来),fgets()就
不会报错;一旦放开,fgets()就会不定时报错(与SIGCHLD信号处理函数agt_chld_exit()中的处理没有
关系,即使agt_chld_exit()是个空函数,一样也会报错)。
P.S,在tt.c中明明没有fork()子进程,怎么会收到SIGCHLD信号呢?是不是因为SIGCHLD是不可靠的
信号? |
|