I’m having trouble using dup2 to make a c program execute a command such as ls /bin | grep grep | grep b. When I comment out the third command and associated pipe it executes ls /bin | grep grep fine, but with the last command it just returns right away. Also when I enter ‘ps’ the processes are still running. I think it’s due to how I close the pipes. My code is below:
int main()
{
int pipeA[2];
int pipeB[2];
pipe(pipeA);
pipe(pipeB);
int pidA,pidB,pidC;
if(pidA = fork())
{
close(pipeA[0]);
dup2(pipeA[1],1);
close(pipeA[1]);
execlp("ls","ls","/bin",NULL);
printf("error\n");
}
if(pidB = fork())
{
close(pipeA[1]);
dup2(pipeA[0],0);
close(pipeA[0]);
close(pipeB[0]);
dup2(pipeB[1],1);
close(pipeB[1]);
execlp("grep","grep","grep",NULL);
printf("error\n");
}
if(pidC = fork())
{
close(pipeB[1]);
dup2(pipeB[0],0);
close(pipeB[0]);
execlp("grep","grep","b",NULL);
printf("error");
}
while(pidA != wait(0)){}
return 0;
}
You aren’t closing enough file descriptors.
Because you didn’t close
pipeAin the secondgrep, you end up with the firstgrepwaiting for input from the pipe the secondgrepstill has open, even though the process will not write to it. Because of that, the firstgrepdoes not finish, so the second doesn’t finish either – even though thelsdoes complete. These comments would apply even if the parent process closed its copies of the pipes – as the corrected code does.Notice how you end up closing all 4 descriptors returned by the two calls to
pipe()in each of the four processes – three children and the parent process.This leaves one residual problem – the process hierarchy is upside down because of your aconventional use of
if (pidA = fork()). You have a child process waiting for its parents. You need to use:Similarly for each of the other two processes. You should also check the
pipe()calls and thefork()calls for failure, just to be sure.When doctored to use
/usr/bininstead of/bin, this program works OK on Mac OS X 10.7.3. It lists three files and then generates the message about ‘Continuing here’: