I tried to run the following simple code:
int main(int argc, char* argv[]) {
int fds[2];
pipe(fds);
int pid1, pid2;
if ((pid1 = fork()) == 0){
close(fds[0]); // close read end
dup2(fds[1], 1); // connect write end
char *argv1[2] = {"echo", "hi"};
execvp(argv1[0], argv1);
}
if ((pid2 = fork()) == 0){
close(fds[1]); // close write end
dup2(fds[0], 0); // connect read end
char *argv2[2] = {"wc", "-c"};
execvp(argv2[0], argv2);
}
int status;
waitpid(pid1, &status, 0);
printf("pid=%d terminated with status=%d\n", pid1, status);
waitpid(pid2, &status, 0);
printf("pid=%d terminated with status=%d\n", pid2, status);
return 0;
}
I was expecting both the echo
and wc
to terminate, but the wc
never does.
The output I get for the above code is just something like below (and the main process gets suspended waiting for the wc
to finish).
pid=2802 terminated with status=0
Any ideas why the second forked process doesn't finish?
I have checked, by trying to read from fds[0]
after a short sleep
at the main process, that the wc
command has indeed read the hi
message from the echo.
You need to close all of the write ends of the pipe. There are 4 copies of that file descriptor, and wc
is not going to terminate until all of them are closed. The echo
will close both of its copies when it terminates, but it's best practice to explicitly close the unused copy before you exec with:
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
You need to also close that file descriptor in the parent before you call waitpid