user1863673
user1863673

Reputation: 17

Create child using fork() inside for loop to run execlp() with 2 pipes using dup

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

Answers (2)

ams
ams

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

ecatmur
ecatmur

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

Related Questions