Search code examples
cforkchild-process

child processes are not terminating correctly in c


Still new in learning about forks and processes and I have this task to create 3 child processes perform some actions and then the parent should print there exit status as they terminate.

The problem I am having is child 1 is terminating earlier and I dont think i am using wait() correctly.

This is my code:

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

int main( int argc, char *argv[] ) {
    pid_t child1,child2, child3,wpid;
    int child1Status,child2Status,child3Status;

child1 = fork();
   if (child1 == 0){
    float marks[8];
    float average = 0.0;
    float sum = 0.0;
    printf("I am child one my pid is %d \n",getpid());
    printf("Please enter 8 marks and I will calcuate the average and highest mark\n");
    for (int i = 0; i < 8; ++i) {
        printf("%i) ",i+1);
    scanf("%f", &marks[i]);
    sum += marks[i];
}
average = sum / 8;
printf("Average = %.2f and highest = %.2f\n", average,highest(&marks));
exit(1);
}
 else{
        
        child2 = fork();
         if (child2 == 0){
    

char *cmd = "wc";
        char *args[4];
    args[0] = "wc";
    args[1] = "-c";
    args[2] = "test.txt";
    args[3] = NULL;
         execvp(cmd, args);
      
         }
         else
        {
           child3 = fork();
            if (child3 == 0){
        

          char *cmd = "wc";
            char *args[4];
            args[0] = "wc";
            args[1] = -c;
            args[2] = "anotherfile.txt";
            args[3] = NULL;
            execvp(cmd, args);
             }
          else
            {

                
                wait(&child1Status);
                printf(" child one has exited with exit status %d \n", (child1Status >> 8));
                wait(&child2Status);
                printf(" child two has exited with exit status %d \n", (child2Status >> 8));
                wait(&child3Status);
                printf(" child three has exited with exit status %d \n", (child3Status  >> 8));
            }

}

In my current output child 1 says it has been exited before I enter in any marks whereas it should say it has been exited after it prints out the highest and average mark.

I also know that because I am using execvp in child2 and 3 then the exit() code wont run, how i can get the exit status in that case?

I also need to print "parent is finished" once all the child processes have been terminated, how can I be sure that all the child processes have terminated before i print "parent is finished"

edit: replaced the last else block with the following due to the comments

else
            {
                
                waitpid( child1,  &child1Status, 0);
                printf(" child one has exited with exit status %d \n", (child1Status >> 8));
                 waitpid( child2,  &child2Status, 0);
                printf(" child two has exited with exit status %d \n", (child2Status & 0x7F));
                 waitpid( child3,  &child3Status, 0);
                printf(" child three has exited with exit status %d \n", (child3Status & 0x80));
            }

With the following above all 3 child processes exit one after each other at the end which should not be the case

expected output:

I am child 1 please enter 8 marks and i will find the average
I am child 2 here is the word count 
50
child 2 has exited 
i am child 3 here is the word count 
96 
child 3 has exited 
**enter 8 marks by user**
average is 
child 1 has exited
parent has finished

Current output:

 I am child 1 please enter 8 marks and i will find the average
    I am child 2 here is the word count 
    50
  i am child 3 here is the word count 
    96 
**enter 8 marks by user**
    average is 
    child 1 has exited
child 2 has exited
child 3 has exited

Solution

  • Your code does not even compile due to various mistakes...

    Anyway, it looks that you want to show the end of the childs as soon as it occurs. For that, you should loop on wait until there is no more child to wait, and use the return value to know which one has ended:

          ...
          else
            {
    
            for(;;) {    
                pid_t pid = wait(&child1Status);
                int child_num;
                if (pid == child1) child_num = 1;
                else if (pid == child2) child_num = 2;
                else if (pid == child3) child_num = 3;
                else break;   // no more child to wait...
    
                printf(" child %d has exited with exit status %d \n",
                       child_num, (child1Status >> 8));
            }
            }
            ...