Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fork in a for loop

Tags:

fork

unix

I have a doubt in the following piece of code and its behaviour:

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

#define N 5
#define nt 1

int pm[N][2],pid[N];
int i,j,size;
char s[100];
int count=0;

int main()
{
 for(i=1;i<N;i++)
    {
      printf("\n i=%d",i);

      if(pid[i]=fork() == -1)
        {
          printf("\n fork not wrking");
          exit(1);
        }
      else if(pid[i]>0)
        {
          printf(" \n pid:%3d\n",pid[i]);
        break;
        }

    }
return 0;
}

I initially thought that the code will spawn a process and skip out of the loop. Thereby,
1 spawns 2 and skips out.
2 spawns 3 and skips out
3 spawns 4 and skips out
4 spawns 5 and skips out.

I tried executing this code and was surprised by the answer i got ( for the printf of i in the code). Here is the output

 i=1
 i=2
 i=3
 i=2
 i=4
 i=3
 i=3
 i=3
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4

Can Anyone please explain to me what is going on here. NOTE: I am working on a Solaris machine.

like image 840
tomkaith13 Avatar asked Dec 29 '22 02:12

tomkaith13


1 Answers

Update

You're missing a set of parentheses in your updated code. That should be if ((pid[i] = fork()) == -1) not if (pid[i] = fork() == -1)!

The latter is equivalent to if (pid[i] = (fork() == -1)) due to precedence rules. It ends up assigning 0 to pid[i] each time through the loop, so the parents think they are child processes and don't break out of the loop.


I agree with your analysis of what should happen. The parent should spawn a child and then quit, so each i=n printout should only show up once.

Are you sure you typed it in exactly as specified in your question? I ran your program (with minor modifications) and got the output you predicted:

$ cat fork.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define N 5

int main() {
    int pid[N], i;

    for(i=1;i<N;i++) /* What’s the total number of processes? */
    {
    printf("i=%d\n",i); // Output of all the is
    if((pid[i]=fork())==-1) exit(1);
    else if(pid[i] > 0) break;
    }

    return 0;
}
$ gcc -o fork fork.c
$ ./fork
i=1
i=2
$ i=3
i=4

Note that I moved the \n in the printout to the end. When you put it at the beginning of the line you end up with stdout not being flushed, so you get multiple printouts when the parent and child processes both flush their output buffers. That might be the cause of your problem. FWIW on my Mac I got each printout twice.

like image 143
John Kugelman Avatar answered Jan 13 '23 12:01

John Kugelman