-1

I'm trying to write a program that has a single parent process create multiple children in a while loop. For testing I started trying to make only 4 processes (1 parent and its 3 children). But it seems like the children are executing code above the line they were created in, even though there is no recursion (to my knowledge) for them to go back to that line.

Here's what I have right now:

int main() {

  time_t start;
  time_t end;
  int i = 0;
  pid_t pid;

  start = time(NULL);
  printf("Αρχική τιμή δευτερολέπτων %d\n", start);

  pid = fork();
  printf("%d ", pid);
  while (i < 2) {
    if (pid > 0) {
      fork();
      wait();
      i++;
    }
  }

  printf("check ");

  printf("%d", pid);

  if (pid > 0) {
    end = time(NULL);
    printf("%d\n", end - start);
  }

  return 0;
}

My output for that is:

Αρχική τιμή δευτερολέπτων 1547394155
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0

So it seems like printf ("%d ", pid) is running 4 times, even though there should only be 2 processes running at the time.

  • wait() typically requires an argument. otherwise, try adding sleep(9999) or similar and then using pstree or something to inspect how the processes are laid out; the fork/wait/while code is very suspect, and printing from both the parent and children processes may run into buffering issues. – thrig Jan 13 at 16:36
  • regarding: pid = fork(); and fork() the function has three different types of returned values. 1) <0 means an error occurred 2) ==0 means the child process is running 3) > 0 means the parent is running. The code should be checking/handling all three conditions – user3629249 Jan 13 at 22:19
  • when asking a question about a runtime problem, as this question is doing, post a [mcve] so we can reproduce the problem and help you to debug it. – user3629249 Jan 13 at 22:21
  • regarding: pid = fork(); printf("%d ", pid); all three conditions from the call to fork() will be executing that printf() statement (hopefully the error condition is not asserted) so the printf() statement will be executed twice. Regarding: fork(); wait(); all three conditions will be executing the wait(), However, only the parent should be executing the wait(). The code really needs to be checking the returned values from the C library functions: wait() and fork() – user3629249 Jan 13 at 22:27
  • BTW: this statement: wait(); will cause a compile problem, because the syntax is: pid_t wait( int *status ) and (int *status) is not the same as () – user3629249 Jan 13 at 22:31
1

This is similar to the issue in "Why does a program with fork() sometimes print its output multiple times?".

The output buffer is not flushed immediately when you do printf("%d ", pid) since the string is not terminated by a newline, and since you don't call fflush(stdout). This means that the unflushed buffer is inherited by the child processes and you get original parent's PID outputted too many times when the buffer finally is flushed by the last printf() call (which outputs a newline) or at the end of the program's execution.

Inserting fflush(stdout) directly after that printf() call (along with including the appropriate headers and calling wait() correctly) will result in something like

Αρχική τιμή δευτερολέπτων 1547400480
79301 0 check 793010
check 793010
check 793010
check 793010

Also note that you will get a process that is indefinitely looping in the while loop (the first child process, whose pid value is zero).

  • Well I think this is not the problem, I tried that one please see it:ideone.com/SDOGlt – Prvt_Yadv Jan 13 at 17:03
  • @P_Yadav With your C++ code, I only get two copies of the 1 line output, as expected. – Kusalananda Jan 13 at 17:16
  • Got it, but can you please one more time look at the link I think output 3 0 should be three times instead of 4 times because first child will get pid value=0, then how can it execute last printf statement of the code? – Prvt_Yadv Jan 13 at 17:37
  • No, it's not that in this case; the ` printf("%d", pid);` will be actually called 4 times ;-) – mosvy Jan 13 at 17:41
  • @mosvy thanks for response but I am not talking about that one, last one means inside the if condition printf("%d\n", end - start);. I am getting this if condition called 4 times. – Prvt_Yadv Jan 13 at 17:44
0

First of all, notice that calling wait() without an argument is not acceptable; it's not the same as wait(NULL); it will either fail with EFAULT or trash memory around when trying to store the status.

I'll try to explain what happens in your code, without running it (I've had my share of fork bombs, thank you very much).

  pid = fork();
  printf("%d ", pid);
  while (i < 2) {
    if (pid > 0) {
      fork();
      wait();
      i++;
    }
  }

After the first fork, you will have 2 processes; pid will be equal to 0 in the child, so the child will continue to run in an infinite loop, because the i++ will be executed only when pid > 0.

From that point on, pid > 0 will be true in the parent and all the children created by the 2nd fork from inside the loop, because the pid variable is never updated again anywhere.

So the fork() from inside the loop will create (1) a child on the first run in the parent, (2) a child on the second run in the parent and (3) yet another child on the second run in the child created in the first run of the loop.

That makes 3 + 1 = 4 processes, which will all run through the end of the main() function, and pid > 0 will be true in all of them, so they will all print out the whole stuff (including the unflushed data added by the printf("%d ", ... just before the while loop).


As a sidenote, you should use dprintf(1 or 2, ...) anytime you want a debugging printf(); that will get any spurious buffering (and spurious fears about it happening) out of the way; dprintf() is now also part of the standard.

  • One process will be stuck in the while loop. The code paths are so confused, I'm not sure what the intended behaviour of this code is supposed to be. – Kusalananda Jan 13 at 18:26
  • I've already mentioned that, but thanks anyways. – mosvy Jan 13 at 18:27
  • So you did. I thought your last paragraph included that process. – Kusalananda Jan 13 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.