0

Here is my sample code called server.c (have removed include's to keep it simple).

int main()
{
    for(int i = 0; i < 10; i++) {
        fork();
        execl("./client", "./client", NULL);
    }
    if (wait(NULL) == -1)
        perror("error with wait");
    return 0;
}

And this is the client code that gets exec'd from the above program.

int main()
{
    printf("This is the child with pid = %d from parent %d", getpid(), getppid());
    return 0;
}

Now let me explain what I think will happen and what I am actually getting as an output.

In server, we enter the for loop. In the first iteration, we hit fork(). At this point there are two processes namely the parent and the first child. Now we exec a program named "client" from both of these processes. This client code just prints some information. So when I run this server program, I should end up getting two lines right? One line from parent and the other from the child? But I only get one line printed and after using strace I found that only parent is printing out stuff, not the child. So why is this?

Is it because the child can no longer be collected since parent is dead(is this the right term?) since it was exec'd? If so, what would happen to the child? It becomes a zombie right? and will it be collected by init? Even so, why won't it print out that line before ending up like a zombie?

posixKing
  • 408
  • 1
  • 8
  • 17
  • When I try your program I get hundreds of `error with wait: No child processes` messages. – Barmar Apr 12 '17 at 22:33
  • 1
    Never mind, I gave the client program the wrong name. When I fixed that, it worked as expected, I got two lines of output. – Barmar Apr 12 '17 at 22:35
  • After the exec(), the progam doesnt exist.The exec is executed is executed in both the parent and the child. The loop will never loop (if exec succeeds) – wildplasser Apr 12 '17 at 22:38
  • 1
    @posixking. please unaccept my answer. It's not correct and I cannot delete it.. – Arash Apr 12 '17 at 22:38

2 Answers2

0

If stdout is connected to a terminal, it should be line-buffered, so there's no need to flush. And all streams are flushed automatically when they're closed, which happens when the program finishes.

Maybe you see both print in the same line? Try this code:

#include <stdio.h>
int main(int argc, char **argv) {
  printf("This is the child with pid = %d from parent %d\n", getpid(), getppid());
  return 0;
}

By the way, you are missing a %d in printf.

Arash
  • 1,950
  • 14
  • 17
  • 1
    If stdout is connected to a terminal, it should be line-buffered, so there's no need to flush. And all streams are flushed automatically when they're closed, which happens when the program finishes. – Barmar Apr 12 '17 at 22:34
  • 1
    good point. I just tried to re-create his case and cannot do it. You're right. deleting... – Arash Apr 12 '17 at 22:35
  • 1
    Thanks & my bad, you are right. I typed the newline character here in stackoverflow, but forgot to type it in my program. Newline also flushes the stream, so it works now. – posixKing Apr 12 '17 at 22:38
  • 1
    @posixKing That shouldn't matter, since returning will flush. Maybe you just didn't see the two messages because they were on the same line? – Barmar Apr 12 '17 at 22:39
0

You should definitely be getting two lines.

If you're not, it's probably due to how you run the program. The parent may print and exit, and if you stop looking or listening at that point you will lose the message from the child.

Due to this, make sure you run the script directly from a shell terminal, and not part of a script, from an IDE, editor, or in any other tool.

For example, here's output of ./server; echo "Done":

user ~ $ ./server; echo "Done."
This is the child with pid = 27904 from parent
Done.

This makes it look like there's only one line of output. However, in the line after this, the prompt has returned and the child process has written some information after it:

user ~ $ This is the child with pid = 27905 from parent

If you run the script in such a way that the shell waits, for example by adding | cat which will wait until the pipe is completely closed, you can see both more clearly:

user ~ $ ./server | cat; echo "Done."
This is the child with pid = 27953 from parent
This is the child with pid = 27955 from parent
Done.
that other guy
  • 116,971
  • 11
  • 170
  • 194