I am trying to write a C program that execute ls | wc
using pipe and fork but I can't figure out what is wrong with my code. When I run the code below nothing is returned.
int main() {
pid_t p1, p2;
int fd1[2];
pipe(fd1);
p1 = fork();
if (p1 == 0) {
close(STDOUT_FILENO);
dup2(fd1[1], STDOUT_FILENO);
close(fd1[0]);
execlp("ls", "ls", (char *)NULL);
} else {
p2 = fork();
if (p2 == 0) {
dup2(fd1[0], STDIN_FILENO);
close(fd1[0]);
close(fd1[1]);
execlp("wc", "wc", (char *)NULL);
} else {
waitpid(p2, 0, WUNTRACED);
waitpid(p1, 0, WUNTRACED);
}
}
return 0;
}
You didn't clearly explain what this program was doing that you considered to be wrong. However, when I run this program myself (after adding the appropriate headers -- in the future, please don't leave those out of your question), it hangs until I press control-C. I'm going to assume that this is what you didn't want, and that what you did want is for it to print the output of wc
and then exit.
The program hangs because fd1[1]
is still open in the parent process at the point when it calls wait
. wc
will not receive an EOF indication until all of the file descriptors referring to the write side of the pipe are closed. But the parent process is not going to close the write side of the pipe until both of its child processes exit, and wc
is not going to exit until it gets an EOF, so you have a deadlock.
You need to add close(fd1[1])
on the parent side of the first if
, immediately before p2 = fork()
. That is sufficient to clear the deadlock. You should also add close(fd1[0])
on the parent side of the second if
, immediately before the waitpid
calls. And you should also check all operations for errors.