Fork () inside fork () inside while loop

Please review my code here. My plan is that I have a while loop. Inside the while loop, I execute the for statement. After the for loop, I use fork. Now I have a parent and child1

. Inside the parent, I execute another fork, giving me the parent and child2

. Now my questions are:

1) why is it when x=3

the "fork1 successful" statement is printed twice?

2) for x=2

, the same problem occurred with x=3

. He said that fork 1 and fork 2 are successful but do not go into both child1

and child2

. It skipped a line n=waitpid(-1, &status, 0);

and just went to print n, then x-- and went tox=1;

3) for x = 1, I think the outputs are really messed up, such as why "child1 pid = 4783" is printed between SENDING 1 and SENDING 2. fork 1 is also printed twice twice.

Please help me fix these problems. I read the posts but I don't see any similar problems. What could I have missed? Thank you very much! Here is a snippet of my code:

while(x>0)
{
    printf("x=%d\n", x);
    for(i=0; i<3; i++)
    {
        printf("SENDING %d\n", i);
    }

    pid1=fork();
    printf("fork1 successful\n");
    if(pid1>0)
    {
        printf("RECEIVING %d\n", i);
        pid2=fork();
        if(pid2>0)
        {
            printf("fork2 successful\n");
            n=waitpid(-1, &status, 0);
            printf("%d\n", n);

            if(n==pid1) //sleep done
            {
                kill(pid2, SIGKILL);
                printf("Child1 ran. Child2 killed.\n\n");
            }

            else if(n==pid2) //scanf received               
            {
                kill(pid1, SIGKILL);
                printf("Child2 ran. Child1 killed.\n\n");
            }
        }    
        else
        {
            printf("child2 pid=%d\n", getpid());            
            scanf("%d", &y);
            exit(1);
        }
    }
    else
    {
        printf("child1 pid=%d\n", getpid());
        sleep(5);
        exit(0);
    }
x--;
}

      

And the following result:

x=3

SENDING 0

SENDING 1

SENDING 2

fork1 successful

RECEIVING 3

fork1 successful

child1 pid=4781

fork2 successful

child2 pid=4782

4781

Child1 ran. Child2 killed.

x=2

SENDING 0

SENDING 1

SENDING 2

fork1 successful

RECEIVING 3

fork1 successful

fork2 successful

4782

x=1

SENDING 0

SENDING 1

child1 pid=4783

SENDING 2

fork1 successful

RECEIVING 3

child2 pid=4784

fork2 successful

child2 pid=4786

fork1 successful

child1 pid=4785

1

4784

      

+3


source to share


1 answer


I assume that you are assuming that it n=waitpid(-1, &status, 0)

will stop until one of the child processes exits. waitpid

will return after any changes in any child process. If you add the variable "x" to the print statements, and also add a statement to display the return value of the status from waitpid

, you will see that in the second loop, where x=2

, the statement is triggered waitpid

when one of the previous loops ends. Everything is chaotic here, since processes can crowd out each other. In the source code, you can see two child1 processes mapped to x = 1.

x=3
[3] SENDING 0
[3] SENDING 1
[3] SENDING 2
[3] fork1 successful
[3] RECEIVING 3
[3] fork2 successful
[3] fork1 successful
[3] child1 pid=8166
[3] child2 pid=8167
[3] child1 exiting
[3] process ID 8166 returned status 0.[3] Child1 ran. Child2 killed.

x=2
[2] SENDING 0
[2] SENDING 1
[2] SENDING 2
[2] fork1 successful
[2] RECEIVING 3
[2] fork1 successful
[2] fork2 successful
[2] process ID 8167 returned status 9.x=1
[1] SENDING 0
[1] SENDING 1
[1] SENDING 2
[2] child1 pid=8171
[2] child2 pid=8172
[1] fork1 successful
[1] RECEIVING 3
[1] fork1 successful
[1] child1 pid=8173
[1] fork2 successful
[1] child2 pid=8174
[2] child1 exiting
[1] child1 exiting
[1] process ID 8171 returned status 0

      

One way to fix this is to check the status waitpid

:



do
{
  n=waitpid(-1, &status, 0);
  printf("[%d] process ID %d returned status %d.", x, n, status);
  if (WIFEXITED(status)==0)
     printf("This is NOT an exit status, so I will keep looping....\n");
  else
     printf("\n");

 } while (WIFEXITED(status)==0);

      

then I believe you will get the expected result:

x=3
[3] SENDING 0
[3] SENDING 1
[3] SENDING 2
[3] fork1 successful
[3] RECEIVING 3
[3] fork2 successful
[3] fork1 successful
[3] child1 pid=8267
[3] child2 pid=8268
[3] child1 exiting
[3] process ID 8267 returned status 0.
[3] Child1 ran. Child2 killed.

x=2
[2] SENDING 0
[2] SENDING 1
[2] SENDING 2
[2] fork1 successful
[2] RECEIVING 3
[2] fork2 successful
[2] process ID 8268 returned status 9.This is NOT an exit status, so I will keep looping....
[2] fork1 successful
[2] child1 pid=8270
[2] child2 pid=8271
[2] child1 exiting
[2] process ID 8270 returned status 0.
[2] Child1 ran. Child2 killed.

x=1
[1] SENDING 0
[1] SENDING 1
[1] SENDING 2
[1] fork1 successful
[1] RECEIVING 3
[1] fork1 successful
[1] child1 pid=8273
[1] fork2 successful
[1] process ID 8271 returned status 9.This is NOT an exit status, so I will keep looping....
[1] child2 pid=8274
[1] child1 exiting
[1] process ID 8273 returned status 0.
[1] Child1 ran. Child2 killed.

      

+1


source







All Articles