Reputation: 17
I am writing a C program which will run Linux commands, like:
$ cat /etc/passwd | cut -f1 -d: | sort
while waiting for the child to complete, only one child terminates with success. The code hangs displaying "running sort"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
int main()
{
int i,fd1[2],fd2[2],status,listpid[3];
pid_t child;
pipe(fd1);
pipe(fd2);
for(i=0; i< 3; i++)
{
printf("\ncreating child\n");
if((child = fork()) == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(child == 0)
{
if(i == 0)
{
close(1); dup(fd1[1]);
close(fd1[0]);
close(fd1[1]);
printf("\nrunning cat /etc/passwd\n");
fflush(stdout);
execlp("cat","cat","/etc/passwd", (char *)NULL);
exit(EXIT_SUCCESS);
}
else if(i == 1)
{
close(0); dup(fd1[0]);
close(fd1[1]);
close(fd1[0]);
close(1); dup(fd2[1]);
close(fd2[1]);
close(fd2[0]);
printf("\nrunning cut -f1 -d:\n");
fflush(stdout);
execlp("cut","cut","-f1","-d:", (char *)NULL);
exit(EXIT_SUCCESS);
}
else if(i == 2)
{
close(0); dup(fd2[0]);
close(fd2[1]);
close(fd2[0]);
close(fd1[0]);
close(fd1[1]);
printf("\nrunning sort\n");
fflush(stdout);
execlp("sort","sort", (char *)NULL);
exit(EXIT_SUCCESS);
}
}
else
{
listpid[i]=child;
}
}
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
for(i = 0; i < 2; i++)
{
waitpid(listpid[i], &status, 0);
if(WIFEXITED(status))
{
printf("\n[%d] TERMINATED (Status: %d)\n",listpid[i], WEXITSTATUS(status));
}
}
exit(EXIT_SUCCESS);
}
Upvotes: 0
Views: 1703
Reputation: 25599
The reason it "hangs" is because sort
is waiting for more input. It won't output anything until the input pipes are closed. There might be something wrong with your pipes (you should check the return values from pipe
and dup
), but I can't see anything.
My guess is that cut
hasn't exited. Again, the most likely reason is that it's input pipe isn't closed. So, where is it open?
It won't be open in the cat
process because there's no reason why that wouldn't have exited.
It won't be open in the parent process because you've carefully closed all the descriptors.
It won't be open in the cut
process because you close the write end of fd1.
That leaves the sort
process itself: that still has fd1's descriptors open!
So, sort
hangs because it's waiting for cut
to finish, and cut
hangs because it's waiting for sort
, even though sort will never write anything to fd1.
You should either close fd1 in the third child, or you should arrange for each pipe to only exist in the children that need them.
That's my theory anyway.
Upvotes: 1
Reputation: 157414
You need to close the pipe fd1
in child 2, otherwise child 1 will hang waiting for more possible input.
As another issue, your waitpid
loop should have loop condition i < 3
, not i < 2
.
Upvotes: 0