【发布时间】:2019-01-07 03:13:39
【问题描述】:
我有一个为了执行子进程而分叉的进程,该子进程接收来自标准输入的条目并写入标准输出。
我的代码简写如下:
int fd[2];
int fd2[2];
if (pipe(fd) < 0 || pipe(fd2) < 0)
throws exception;
pid_t p = fork();
if (p == 0) // child
{
close(fd[0]); //not needed
dup2( fd[1],STDOUT_FILENO);
dup2( fd[1],STDERR_FILENO);
close(fd2[1]); //not needed
//what if write calls on parent process execute first?
//how to handle that situation
dup2( fd2[0],STDIN_FILENO);
string cmd="./childbin";
if (execl(cmd.c_str(),(char *) NULL) == -1)
{
exit (-1);
}
exit(-1);
}
else if (p > 0) // parent
{
close(fd[1]); //not needed
close(fd2[0]);
if (write(fd2[1],command.c_str(),command.size())<0)
{
throw exception;
}
close(fd2[1]);
//waits for child to finish.
//child process actually hangs on reading for ever from stdin.
pidret=waitpid(p,&status,WNOHANG))==0)
.......
}
子进程一直在等待 STDIN 中的数据。子进程和父进程之间是否存在竞争条件?我认为这可能是问题所在,但不太确定,也不知道如何解决。
提前致谢。
更新: 一些有用的信息。 父进程是一个守护进程,此代码每秒运行几次。它在 97% 的情况下工作(约 3% 的情况下,子进程保持在前面描述的状态)。
更新 2 在 dup2 调用中添加验证后,那里没有错误,永远不会引发下一个条件。
if(dup2(...) == -1) {
syslog(...)
}
【问题讨论】:
-
dup2 3% 失败案例的返回值/errno 是多少?
-
@Surt 实际上,我意识到我没有处理来自 dup2 的返回。我将更新代码并进行测试。谢谢!
-
也许我遗漏了一些东西,但是为什么你需要为父->子通信创建一个管道?您不能按原样使用 STDOUT/STDIN 吗?还有多少写在管道上?如果您的孩子超过
PIPE_BUF写入,它将阻止等待管道被清空,但您的父母已经在waitpid()上被阻止 - 可能不是这里的问题,但以后可能会引起关注。