1

I have been trying to figure out how to loop through stdin from a file, then send it to a child process who sorts int using execl(). The code below works in that it takes the file & sorts the lines, but I am not seeing the "end of sentence" debug string I have added. Somehow this part of the code is being bypassed. I could use some help understanding the flow of data as it comes in from the file, then gets printed out to the screen.

int main(int argc, char *argv[])
{
  pid_t p;
  int status;
  int fds[2];
  FILE *writeToChild;
  char word[50];

  if(pipe(fds) == -1) {
    perror("Error creating pipes");
    exit(EXIT_FAILURE);
  }

  switch(p = fork()) {
  case 0: //this is the child process
    close(fds[1]); //close the write end of the pipe
    execl("/usr/bin/sort", "sort", (char *) 0);
    break;
  case -1: //failure to fork case
    perror("Could not create child");
    exit(EXIT_FAILURE);
  default: //this is the parent process
    close(fds[0]); //close the read end of the pipe
    writeToChild = fdopen(fds[1], "w");
    wait(&status);
    break;
  }

  while (fscanf(stdin, "%s", word) != EOF) {
    //the below isn't being printed.  Why?
    fprintf(writeToChild, "%s end of sentence\n", word); 
  }

  return 0;
}

1 Answer 1

2

Your primary problem is that you have the wait() in the wrong place. You wait for the child to die before you've written anything to it. You also have a secondary problem that don't redirect the read end of the pipe to the sort process's standard input.

You're not closing fds[0] in the child; cleanliness suggests that you should. You do need to fclose(writeToChild) before waiting; the sort won't stop until the parent has closed the pipe to the child.

These changes (and a few other ones) lead to:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    pid_t p;
    int status;
    int fds[2];
    FILE *writeToChild;
    char word[50];

    if (pipe(fds) == -1)
    {
        perror("Error creating pipes");
        exit(EXIT_FAILURE);
    }

    switch (p = fork())
    {
        case 0: //this is the child process
            close(fds[1]); //close the write end of the pipe
            dup2(fds[0], 0);
            close(fds[0]);
            execl("/usr/bin/sort", "sort", (char *) 0);
            fprintf(stderr, "Failed to exec sort\n");
            exit(EXIT_FAILURE);

        case -1: //failure to fork case
            perror("Could not create child");
            exit(EXIT_FAILURE);

        default: //this is the parent process
            close(fds[0]); //close the read end of the pipe
            writeToChild = fdopen(fds[1], "w");
            break;
    }

    if (writeToChild != 0)
    {
        while (fscanf(stdin, "%49s", word) != EOF)
        {
            //the below isn't being printed.  Why?
            fprintf(writeToChild, "%s end of sentence\n", word); 
        }
        fclose(writeToChild);
    }

    wait(&status);

    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

That is a huge help. Thank you. I have couple follow up questions. The line dup2(fds[0], 0); duplicates the read end of the fds pipe? It also looks like you close the read end of the pipe right after with close(fds[0]);? If so, why close it before calling excel to sort?
The dup2() makes sure that the sort's standard input is the pipe, but you only need one of the two file descriptors (0 and fds[0]) open, so you close the second descriptor. This is normal when you duplicate a pipe to standard input or standard output; you close both ends of the pipe returned by pipe() if you use dup2() to connect that pipe to standard input or standard output. Since the parent process writes to the pipe (without using dup2()), it does not close the end of the pipe it is writing to until it is finished. You could use dup2(fds[1], 1) and close fds[1] in the parent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.