Home > Blockchain >  C program yields two process trees instead of one
C program yields two process trees instead of one

Time:12-05

If my interpretation is right, from the following C program one expects to obtain one process tree, where from one father process, three child processes and two grandchild processes are generated:

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

int main(int argc, char *argv[])
{
    int num;
    pid_t t;
    for (num = 0; num < 2; num  ) {
        t = fork();
        if (t == 0)
        break;
    }
    t = fork();
    printf("I am the process %d and my father is %d\n", getpid(), getppid());
    return 0;
}

However, after compiling and executing, the output turns out to be as follows:

I am the process 2133 and my father is 2127
I am the process 2134 and my father is 2133
I am the process 2137 and my father is 778
I am the process 2135 and my father is 778
I am the process 2138 and my father is 778
I am the process 2136 and my father is 778

As expected, six processes are produced, but four of them are spawned by the process #778. On the other hand, just one of them (#2134) seems to be fathered by the initial process (#2133). In total two process trees have been produced instead of one.

Why this behavior? Does it mean that those above mentioned four processes have been adopted/reclaimed by the process #778?

CodePudding user response:

As pointed out in the comments, you're not waiting for the children to finish in the parent, so orphaned processes are being reclaimed by the shell after their parents exit.

The correct tree structure is:

   1
   |
   2
 / | \
3  4  5
|  |
6  7

where:

  • 1 is the shell
  • 2 is your main program; it spawns 3 and 4 in its loop and 5 after the loop
  • 3 and 4 are children spawned in the loop by 2; each spawns 1 new child (6 and 7) after it exists the loop on break
  • 5 is spawned after the loop and therefore is a leaf process
  • 6 and 7 are leaf processes spawned after the loop by 3 and 4

Here's cleaned-up code that will give comprehensible output:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
    printf("original process is %d\n", getpid());

    for (int num = 0; num < 2; num  ) {
        if (fork() == 0) { // 0 means child
            break;
        }
    }

    fork(); // fork after the loop
    printf("I am %d and my parent is %d\n", getpid(), getppid());

    while (wait(NULL) > 0) {} // wait for each child process

    return 0;
}

Sample output:

original process is 540
I am 540 and my parent is 1
I am 541 and my parent is 540
I am 543 and my parent is 541
I am 542 and my parent is 540
I am 544 and my parent is 540
I am 545 and my parent is 542
  • Related