0

Inside a while(1) I'm trying to:

  • spawn a child process with fork();

  • redirect the child process stdout so that the parent process can see it

  • print the result in the terminal from the parent process

  • repeat

Strangely, the output from the child process seems to be printed twice

// parentToChild  and  childToParent are the pipes I'm using

while(1) {

int pid = fork();
    if(pid < 0) {
    // error, get out
    exit(0);
} else if(pid != 0) {
    // parent process
    close(parentToChild[0]); // don't need read end of parentToChild
    close(childToParent[1]); // don't need write end of childToParent

    sleep(4);
    char respBuffer[400];
    int respBufferLength = read(childToParent[0], respBuffer, sizeof(respBuffer));
    printf("before\n");
    printf("parent tried to read something from its child and got: %s\n", respBuffer);
    printf("after\n");
} else if (pid == 0) {
    if(dup2(childToParent[1], STDOUT_FILENO) < 0) {
        // printf("dup2 error");
    };
    close(childToParent[1]);       
    close(childToParent[0]);

    close(parentToChild[1]);    // write end of parentToChild not used

    printf("child message");

    // if we don't exit here, we run the risk of repeatedly creating more processes in a loop
    exit(0);
}
}

I would expect the ouput of the following loop at each iteration to be:

before
parent tried to read something from its child and got: child message
after

But instead, at each iteration I get:

before
parent tried to read something from its child and got: child message
after
child message

What's the reason behind the second print of "child message"?

Flushing the stdout buffers before calling fork() doesn't seem to solve the issue

Interestingly, removing the while loop and keeping everything else intact seems to work fine

TCdrone
  • 3
  • 1
  • Do you get the double message if you remove the loop? – Gwyn Evans May 11 '19 at 21:16
  • I don't, just updated the question, without the loop I don't get any repetition – TCdrone May 11 '19 at 21:16
  • Chris's answer is the scenario I was wondering about in that case. The commenting out of the checking of the result of dup2 was intriguing! – Gwyn Evans May 11 '19 at 21:18
  • Uncommenting the print statement under dup2 doesn't print an error in the terminal, can I assume dup2 is not failing? If it is, why the uncommented line doesn't get printed? – TCdrone May 11 '19 at 21:29

1 Answers1

1

In the first iteration of the loop, you close childToParent[1] in the parent, and you don't recreate the pipes, so in the second iteration of the loop, its trying to reuse those closed pipes, so the child's dup2 call fails, so its printf goes to the terminal. Meanwhile, in the parent, the read call returns 0 without writing anything to the buffer, so you just print the old contents.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Though I always reread the message at each iteration of the loop, before it gets printed again, why is that? – TCdrone May 11 '19 at 21:19
  • Modify the child to print a different message each time, @TCdrone, and see whether you get a different message each time. You don't check most of the system calls for success — specifically not the `read()` — so you've no idea what's working and what's not. – Jonathan Leffler May 11 '19 at 21:23
  • To be safe, (a) initialise your string buffers with '\0' in the first element & if you're looping, re-initialise each time round the loop – Gwyn Evans May 11 '19 at 21:24
  • I see now that the read() call fails and returns 0, but I would expect dup2 to also print an error if I uncomment the line under the if statement, but apparently no error is printed to the console, why is that? Thank you all for your answers, I'll accept this one in a moment – TCdrone May 11 '19 at 21:31