当前位置: 技术问答>linux和unix
主进程select,子进程退出会产生EINTR信号么?
来源: 互联网 发布时间:2016-10-05
本文导语: while(1) { /*提示连接哪种服务*/ ... if((chpid = fork()) == 0) { close(pfd[0]); dup2(pfd[1], 5); close(pfd[1]); ...
while(1)
{
/*提示连接哪种服务*/
...
if((chpid = fork()) == 0)
{
close(pfd[0]);
dup2(pfd[1], 5);
close(pfd[1]);
execlp("xterm", "xterm", "-e", "./echo_cli", addr, (char *) 0);
} else {
FD_ZERO(&rset);
while(1)
{
maxfdp1 = max(pfd[0], fileno(stdin)) + 1;
FD_SET(pfd[0], &rset);
FD_SET(fileno(stdin), &rset);
select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(pfd[0], &rset))
{
if((nread = read(pfd[0], buff, MAXLINE)) > 0)
{
buff[nread] = 0;
fputs(buff, stdout);
} else break;
}
if(FD_ISSET(fileno(stdin), &rset))
{
if((nread = read(fileno(stdin), buff, MAXLINE)) > 0)
fputs("Do not type in the parent window!n", stdout);
}
else
{
if(errno == EINTR)
break;
}
}
}
void
sig_chld(int signo)
{
pid_t pid;
int stat;
char buff[MAXLINE];
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
sprintf(buff, "---Disconnected from server...---n");
fputs(buff, stdout);
}
return;
}
我写了一个socket连接的代码,进入子进程后会产生一个xterm窗口与服务器进行通信,我希望在开启xterm窗口后,
1创建一个管道与夫进程通信,传输一些连接信息
2如果在parent继续输入,则会提示Do not type in the parent window!
3xterm通过ctrl D 或 ctrl C退出后,主进程回到外层的while循环继续询问要连接哪种服务
为了做到这三点,定义了信号处理函数来处理SIG_CHLD,一旦子进程退出就会打印---Disconnected from server...并
并在主进程里用select监听管道的输出端pfd[0]和stdin,哪个描述符产生了可读信息就打印
可是现在一旦退出xterm(子进程),父进程窗口就会停在---Disconnected from server...---处,不会返回外层的while(1)循环,我认为此时父进程应该还阻塞在为select写的内层while(1)里,可是如何通知主进程子进程已经退出呢?
可以通过判断errno==EINTR么?我在内层while(1)里加了判断errno的代码,但是没有什么用,请高手赐教
{
/*提示连接哪种服务*/
...
if((chpid = fork()) == 0)
{
close(pfd[0]);
dup2(pfd[1], 5);
close(pfd[1]);
execlp("xterm", "xterm", "-e", "./echo_cli", addr, (char *) 0);
} else {
FD_ZERO(&rset);
while(1)
{
maxfdp1 = max(pfd[0], fileno(stdin)) + 1;
FD_SET(pfd[0], &rset);
FD_SET(fileno(stdin), &rset);
select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(pfd[0], &rset))
{
if((nread = read(pfd[0], buff, MAXLINE)) > 0)
{
buff[nread] = 0;
fputs(buff, stdout);
} else break;
}
if(FD_ISSET(fileno(stdin), &rset))
{
if((nread = read(fileno(stdin), buff, MAXLINE)) > 0)
fputs("Do not type in the parent window!n", stdout);
}
else
{
if(errno == EINTR)
break;
}
}
}
void
sig_chld(int signo)
{
pid_t pid;
int stat;
char buff[MAXLINE];
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
sprintf(buff, "---Disconnected from server...---n");
fputs(buff, stdout);
}
return;
}
我写了一个socket连接的代码,进入子进程后会产生一个xterm窗口与服务器进行通信,我希望在开启xterm窗口后,
1创建一个管道与夫进程通信,传输一些连接信息
2如果在parent继续输入,则会提示Do not type in the parent window!
3xterm通过ctrl D 或 ctrl C退出后,主进程回到外层的while循环继续询问要连接哪种服务
为了做到这三点,定义了信号处理函数来处理SIG_CHLD,一旦子进程退出就会打印---Disconnected from server...并
并在主进程里用select监听管道的输出端pfd[0]和stdin,哪个描述符产生了可读信息就打印
可是现在一旦退出xterm(子进程),父进程窗口就会停在---Disconnected from server...---处,不会返回外层的while(1)循环,我认为此时父进程应该还阻塞在为select写的内层while(1)里,可是如何通知主进程子进程已经退出呢?
可以通过判断errno==EINTR么?我在内层while(1)里加了判断errno的代码,但是没有什么用,请高手赐教
|
按楼主所给的代码片断以及所说的要求,我简单完整了一下代码。
用strace跟踪后,发现主进程是阻塞在select()函数这,用kill -17(SIGCHLD),发现程序也没有从select中跳出来。
用strace跟踪后,发现主进程是阻塞在select()函数这,用kill -17(SIGCHLD),发现程序也没有从select中跳出来。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 1024
#define MAX(a, b) (a>b?a:b)
#define debug(fmt...)
do {
fprintf(stdout, "%s[%d] ", __FILE__, __LINE__);
fprintf(stdout, fmt);
}while(0)
void proc()
{
fd_set rset;
int pfd[2];
int maxfdp1;
int nread;
char buff[MAXLINE+1];
pid_t chpid;
pfd[0] = open("p1", O_RDWR);
//while(1)
{
if((chpid = fork()) == 0)
{
close(pfd[0]);
dup2(pfd[1], 5);
close(pfd[1]);
execlp("xterm", "xterm", "-e", "cat", ">", "p1", (char *)0);
}
else
{
FD_ZERO(&rset);
while(1)
{
maxfdp1 = MAX(pfd[0], fileno(stdin)) + 1;
FD_SET(pfd[0], &rset);
FD_SET(fileno(stdin), &rset);
select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(pfd[0], &rset))
{
if((nread = read(pfd[0], buff, MAXLINE)) > 0)
{
buff[nread] = 0;
fputs(buff, stdout);
}
else
break;
}
if(FD_ISSET(fileno(stdin), &rset))
{
if((nread = read(fileno(stdin), buff, MAXLINE)) > 0)
fputs("Do not type in the parent window!n", stdout);
}
else
{
if(errno == EINTR){
debug("===== 200 =====n");
break;
}
}
}
}
}
close(pfd[0]);
return;
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
char buff[MAXLINE];
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
debug("===== 100 =====n");
sprintf(buff, "---Disconnected from server...---n");
fputs(buff, stdout);
}
return;
}
int main(int argc, char *argv[])
{
//signal(SIGCHLD, sig_chld);
proc();
return 0;
}
|
刚才试验了一下
lz试试在父进程中首先调用close(pfd[1]);
...
lz试试在父进程中首先调用close(pfd[1]);
...
} else {
close(pfd[1]);
FD_ZERO(&rset);
while(1)