Question

I am trying to implement multi pipe in C, to run multiple commands like a shell. I have made a linked list (called t_launch in my code) which look like that if you type "ls | grep src | wc" :

wc -- PIPE -- grep src -- PIPE -- ls

Every PIPE node contain an int tab[2] from the pipe() function (of course, there have been one pipe() call for each PIPE node)

Now i am trying to execute these commands :

int     execute_launch_list(t_shell *shell, t_launch *launchs)
{
   pid_t pid;
   int   status;
   int   firstpid;

   firstpid = 0;
   while (launchs != NULL)
   {
      if ((pid = fork()) == -1)
         return (my_error("Unable to fork\n"));
      if (pid == 0)
      {
         if (launchs->prev != NULL)
         {
            close(1);
            dup2(launchs->prev->pipefd[1], 1);
            close(launchs->prev->pipefd[0]);
         }
         if (launchs->next != NULL)
         {
            close(0);
            dup2(launchs->next->pipefd[0], 0);
            close(launchs->next->pipefd[1]);
         }
        execve(launchs->cmdpath, launchs->words, shell->environ);
      }
      else if (firstpid == 0)
        firstpid = pid;
      launchs = launchs->next == NULL ? launchs->next : launchs->next->next;
   }
   waitpid(firstpid, &status, 0);
   return (SUCCESS);
}

But that doesn't work : it looks like commands dont stop reading. For example if i type "ls | grep src, "src" will be print from the grep command, but the grep continue reading and never stop. If i type "ls | grep src | wc", nothing is printed. What's wrong with my code ? Thank you.

Was it helpful?

Solution

If I understand your code correctly, you first call pipe in the shell process for every PIPE. You then proceed to fork each process.

While you do close the unused end of each of the child's pipes in the child process, this procedure suffers from two problems:

  1. Every child has every pipe, and doesn't close the ones which don't belong to it

  2. The parent (shell) process has all the pipes open.

Consequently, all the pipes are open, and the children don't get EOFs.

By the way, you need to wait() for all the children, not just the last one. Consider the case where the first child does some long computation after closing stdout, but remember that any computation or side-effect after stdout is closed, even a short one, could be sequenced after the sink process terminates since multiprocessing is essentially non-deterministic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top