1

would it be possible to help me with creation of short program in which parent process produces 1 child process, the child produces the next child, the subsequent child produces the next child, etc. .... so that all children are in total 16. How can I using the pstree command, present the tree of these processes ? Till now I was able to write something like, but I’ not sure if its correct:

int main()
{
    for(int i = 0; i < 16; ++i)
    {
        pid_t pid = fork();
        if(pid != 0)
        {
            waitpid(pid, NULL, 0);
            return 0;
        }
    }

    sleep(5);
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
axel_87
  • 37
  • 6
  • When you ran `pstree`, what happened? – Ry- Apr 29 '19 at 23:45
  • 2
    Not an answer to your question, but mind that `fork` returns `-1` on error, this isn't critical in your program, but a good habit to check. – johannes Apr 29 '19 at 23:47
  • The first thing to do is add appropriate diagnostic printing, which will include the PID and probably PPID (functions `getpid()` and `getppid()`). Upgrade the `waitpid()` call: `int status; int corpse = waitpid(pid, &status, 0);` and print `corpse` (the PID of the process that died) and its status (`printf("%d: child %d exited with status 0x%.4X\n", (int)getpid(), corpse, status);` or thereabouts). Consider whether the `return 0;` inside the `if` should be `break;`, or whether you should have a `sleep(1);` there (5 is probably too big). – Jonathan Leffler Apr 29 '19 at 23:54
  • 1
    actually, should be enough to replace `sleep(5)` with `system("pstree -lhp")` or somesuch – jhnc Apr 30 '19 at 00:12

1 Answers1

1

As I noted in a comment, add diagnostic printing to help you understand what's going on. Key values are the loop control, i, the PID and PPID of the process, and the value in the pid variable. You also want to instrument the waitpid() call.

That leads to code like this:

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

int main(void)
{
    for (int i = 0; i < 16; ++i)
    {
        pid_t pid = fork();
        printf("%d: (PPID = %d) - post fork %d: pid = %d\n",
               (int)getpid(), (int)getppid(), i, (int)pid);
        fflush(0);
        if (pid != 0)
        {
            int status;
            int corpse = waitpid(pid, &status, 0);
            printf("%d: (PPID = %d) child %d exited with status 0x%.4X\n",
                   (int)getpid(), (int)getppid(), corpse, status);
            fflush(0);
            return 0;
        }
    }

    printf("%d: (PPID = %d) sleeping\n", (int)getpid(), (int)getppid());
    fflush(0);
    sleep(5);
    return 0;
}

The fflush() calls aren't necessary if you run the output to a terminal. If you run the output through a pipe (like I did when generating the output below), they become crucial. See also printf() anomaly after fork(). If you replaced the return 0; in the if with return i;, you'd also get some interesting information.

Running that program leads to output similar to this:

74830: (PPID = 72799) - post fork 0: pid = 74833
74833: (PPID = 74830) - post fork 0: pid = 0
74833: (PPID = 74830) - post fork 1: pid = 74834
74834: (PPID = 74833) - post fork 1: pid = 0
74834: (PPID = 74833) - post fork 2: pid = 74835
74835: (PPID = 74834) - post fork 2: pid = 0
74835: (PPID = 74834) - post fork 3: pid = 74836
74836: (PPID = 74835) - post fork 3: pid = 0
74836: (PPID = 74835) - post fork 4: pid = 74837
74837: (PPID = 74836) - post fork 4: pid = 0
74837: (PPID = 74836) - post fork 5: pid = 74838
74838: (PPID = 74837) - post fork 5: pid = 0
74838: (PPID = 74837) - post fork 6: pid = 74839
74839: (PPID = 74838) - post fork 6: pid = 0
74839: (PPID = 74838) - post fork 7: pid = 74840
74840: (PPID = 74839) - post fork 7: pid = 0
74840: (PPID = 74839) - post fork 8: pid = 74841
74841: (PPID = 74840) - post fork 8: pid = 0
74841: (PPID = 74840) - post fork 9: pid = 74842
74842: (PPID = 74841) - post fork 9: pid = 0
74842: (PPID = 74841) - post fork 10: pid = 74843
74843: (PPID = 74842) - post fork 10: pid = 0
74843: (PPID = 74842) - post fork 11: pid = 74844
74844: (PPID = 74843) - post fork 11: pid = 0
74844: (PPID = 74843) - post fork 12: pid = 74845
74845: (PPID = 74844) - post fork 12: pid = 0
74845: (PPID = 74844) - post fork 13: pid = 74846
74846: (PPID = 74845) - post fork 13: pid = 0
74846: (PPID = 74845) - post fork 14: pid = 74847
74847: (PPID = 74846) - post fork 14: pid = 0
74847: (PPID = 74846) - post fork 15: pid = 74848
74848: (PPID = 74847) - post fork 15: pid = 0
74848: (PPID = 74847) sleeping
74847: (PPID = 74846) child 74848 exited with status 0x0000
74846: (PPID = 74845) child 74847 exited with status 0x0000
74845: (PPID = 74844) child 74846 exited with status 0x0000
74844: (PPID = 74843) child 74845 exited with status 0x0000
74843: (PPID = 74842) child 74844 exited with status 0x0000
74842: (PPID = 74841) child 74843 exited with status 0x0000
74841: (PPID = 74840) child 74842 exited with status 0x0000
74840: (PPID = 74839) child 74841 exited with status 0x0000
74839: (PPID = 74838) child 74840 exited with status 0x0000
74838: (PPID = 74837) child 74839 exited with status 0x0000
74837: (PPID = 74836) child 74838 exited with status 0x0000
74836: (PPID = 74835) child 74837 exited with status 0x0000
74835: (PPID = 74834) child 74836 exited with status 0x0000
74834: (PPID = 74833) child 74835 exited with status 0x0000
74833: (PPID = 74830) child 74834 exited with status 0x0000
74830: (PPID = 72799) child 74833 exited with status 0x0000

If you were feeling even more fussy, you could add timing to the printing operations — you'd probably need to report at the microsecond level to see much difference.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278