The most common reason for this is that you aren't closing the write end of the pipe, so the EOF never gets sent. The common example is when you have code that looks like:
int fds[2];
pipe(fds); // open a pipe
if (fork()) {
// parent process
write(fds[1], ... // write data
close(fds[1]); // close it
} else {
// child process
while (read(fds[0], ....) > 0) {
// read until EOF
The problem here is that the write end of the pipe never gets closed -- the parent process closes it, but the child still has the write descriptor open. So the child never sees an EOF on the read descriptor.
The very first thing you need to do after forking the child is to close(fds[1]);
, closing its copy of the write descriptor. That way when the parent closes the last remaining reference to the write end of the pipe, the child will see EOF on the read end.
Edit
looking at the link you added, this is precisely the problem -- the child still has the write end of the pipe open on its stdout. Don't dup the write end to stdout in the child, just close it. Send stdout somewhere else (a logfile, or /dev/null)
Edit
for bi-drectional communication, you'll need two pipes:
int tochild[2], fromchild[2];
pipe(tochild); pipe(fromchild);
if (fork()) {
close(tochild[0]);
close(fromchild[1]);
//write to tochild[1] and read from fromchild[0]
} else {
dup2(tochild[0], 0);
dup2(fromchild[1], 1);
close(tochild[0]); close(tochild[1]);
close(fromchild[0]); close(fromchild[1]);
exec(...
}
You need to be very careful writing data in the parent, however -- if there's a lot of data to be
sent to the child, you can't send all of it before reading the child's output or you might deadlock (both pipes fill up and the parent blocks trying to write more data for the child while the child blocks trying to output). You need to use poll or select to tell when there's data to read or space to write, and you may want to put the pipes (the parent ends at least) in non-blocking mode.