Thread: fork() and zombies

  1. #1
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136

    fork() and zombies

    run the following code, at first attempt, enter the number when asked...everything works fine
    in the second attempt dont enter any number, let the timer process expire. then...all hell breaks loose...
    Code:
    /* This program checks if the user has "5" as input before the countdown is over or not*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<signal.h>
    
    int main()
    {
        int x,i=0,pid;
        char ch;
        system("clear");
        for(x=0;x<3;x++)
        {
                system("clear");
                if((pid=fork()) == 0)
                {
                   
                    for(i=5;i>0;i--)
                    {                   
                        printf("X=%d\tenter number(ppid=%d,pid=%d)",x,getppid(),getpid());
                        printf("\t\t\t\t\t\t\t%d\a\n",i);
                        sleep(1);
                        system("clear");                                                           
                    }                
                }
    
                else
                {       
                    scanf("%d",&i);      //<--------this is my problem...
                    system("clear");
                    kill(pid,SIGKILL);                                  
                    printf("i=%d",i);                                 
                }
      
                 
                if(i==5)
                {
                    printf("YES i=5\n");                
                }
                else
                {
                    printf("NO i!=5\n");                
                }
                sleep(3);                
        }
        printf("THE END\n");
        return 0;    
    }
    This program checks if the user has "5" as input before the countdown is over or not.

    when i enter a number before the timer exits the for loop...everything is ok.
    but suppose i dont enter anything and the child process finishes its execution, but the parent process continues to wait for user input...
    but if i dont enter anything for all the three iterations,
    this is what i have
    Code:
    [c_d@localhost C scratchpad]$ ps -A | grep "a.out"
    30245 pts/4    00:00:00 a.out
    30248 pts/4    00:00:00 a.out
    30269 pts/4    00:00:00 a.out
    30291 pts/4    00:00:00 a.out <defunct>        #Scooby Doo?! Where are you?
    each of these process would further spawn more process...it goes out of control and beyond my comprehension ,if user does not consistently give the input...

    what i would want is to somehow be able to take the user input,for him,like 0 when the countdown expires and child process is ready to terminate...is that possible?
    Last edited by creeping death; 03-28-2009 at 10:07 PM.
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  2. #2
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136

    no more zombies...but code still not proper...

    i have modified the code...

    Code:
    /* This program checks if the user has "5" as input before the countdown is over or not*/
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<signal.h>
    
    int main()
    {
        int x,i=0,pid,pid2;
        system("clear");
        for(x=0;x<3;x++)
        {
            pid=-1;pid2=-1;
            if((pid=fork()) == 0)   //child process- the countdown timer
            {
                pid=getpid();
                for(i=5;i>0;i--)    //start a 5 sec countdown
                {                   
                    printf("X=%d\tenter number(ppid=%d,pid=%d)",x,getppid(),getpid());
                    printf("\t\t\t\t\t\t\t%d\a\n",i);
                    sleep(1);                                                                     
                }
                exit(666+x);      //exit when 5 secs are over
            }
    
            else      //parent process
            {       
               if((pid2=fork()) == 0)   //create a seperate child process for input
               { 
                    pid2=getpid();
                    printf("\n\nscanf pid2=%d\n\n",pid2);
                    scanf("%d",&i);
                    kill(pid,SIGKILL);     //when input is recieved kill the timer process
                     if(i==5)             //check the user input 
                    {
                       printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);                
                    }
                    else
                    {
                        printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);                
                    }                 
                    exit(777+i);
               }     
               wait();      //wait for child process...timer process.         
               sleep(3);     //take a deep breath
               printf("\n\npid2=%d(i must execute only after wait() is over)\n\n",pid2);                                       
               if((kill(pid2,SIGKILL))==0)  //after the timer child process finishes ,if input process is still running...kill it
               {
                   printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);//default msg
               }   
            }
        }
        printf("THE END(pid=%d\n",getpid());       //this should be executed when all other child processes are over.
        return 0;    
    }
    but still, i get a lot of unexpected behaviour this one for example

    Code:
    X=0	enter number(ppid=24800,pid=24802)							5
    
    
    scanf pid2=24803
    
    X=0	enter number(ppid=24800,pid=24802)							4
    X=0	enter number(ppid=24800,pid=24802)							3
    X=0	enter number(ppid=24800,pid=24802)							2
    X=0	enter number(ppid=24800,pid=24802)							1
    
    
    pid2=24803(i must execute only after wait() is over)
    
    
    NO i!=5(pid=24800) for x=0 #its ok till here...it waited till timer exited then executed the rest,killing scanf process.
    
    X=1	enter number(ppid=24800,pid=24812)	#new timer process						5
    
    
    scanf pid2=24813    #new child scanf process
    
    X=1	enter number(ppid=24800,pid=24812)							4
    X=1	enter number(ppid=24800,pid=24812)							3
    
    
    pid2=24813(i must execute only after wait() is over) #why didnt it wait till timer process exited?
    
    
    NO i!=5(pid=24800) for x=1 #this killed my scanf before the timer expired.
    
    X=1	enter number(ppid=24800,pid=24812)							2
    X=2	enter number(ppid=24800,pid=24817)							5
    
    
    scanf pid2=24818   # x=2 has started before x=1 even finished
    
    X=1	enter number(ppid=24800,pid=24812)							1   
    #the sleep(3) statement never executed again
    X=2	enter number(ppid=24800,pid=24817)							4
    X=2	enter number(ppid=24800,pid=24817)							3
    X=2	enter number(ppid=24800,pid=24817)							2
    
    
    pid2=24818(i must execute only after wait() is over)
    
    
    NO i!=5(pid=24800) for x=2
    
    THE END(pid=24800    #the parent exits , leaving the timer process an orphan
    [c_d@localhost C scratchpad]$ X=2	enter number(ppid=1,pid=24817)							1
    the unexpected behaviour is highlighed with red...and commentaries are written by side of output in blue...

    please comment.
    Last edited by creeping death; 03-30-2009 at 05:48 AM.
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  3. #3
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    well,

    i just changed from wait to waitpid() and there has been a lot of improvement.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<signal.h>
    
    int main()
    {
        int x,i=0,pid,pid2,status,r;
        system("clear");
        for(x=0;x<3;x++)
        {
            pid=-1;pid2=-1;
            if((pid=fork()) == 0)   //child process- the countdown timer
            {
                pid=getpid();
                for(i=5;i>0;i--)    //start a 5 sec countdown
                {                   
                    printf("X=%d\tenter number(ppid=%d,pid=%d)",x,getppid(),getpid());
                    printf("\t\t\t\t\t\t\t%d\a\n",i);
                    sleep(1);                                                                     
                }
                exit(111+x);      //exit when 5 secs are over
            }
    
            else      //parent process
            {       
               if((pid2=fork()) == 0)   //create a seperate child process for input
               { 
                    pid2=getpid();
                    //printf("\n\nscanf pid2=%d\n\n",pid2);
                    scanf("%d",&i);
                    kill(pid,SIGKILL);     //when input is recieved kill the timer process
                     if(i==5)             //check the user input 
                    {
                       printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);                
                    }
                    else
                    {
                        printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);                
                    }                 
                    exit(0);
               }     
            
               r=waitpid(pid,&status); //wait for child process...timer process.         
               
               sleep(3);     //take a deep breath
               printf("\n\npid=%d,pid2=%d(wait status=%d,r=%d)\n\n",pid,pid2,status,r);                                       
               if((kill(pid2,SIGKILL))==0)  //after the timer child process finishes ,if input process is still running...kill it
               {
                   printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);//since the user did not enter anything within time.display this
               }   
            }
        }
        printf("THE END(pid=%d\n",getpid());       //this should be executed when all other child processes are over.
        return 0;    
    }
    output:
    Code:
    X=0	enter number(ppid=7095,pid=7097)							5
    X=0	enter number(ppid=7095,pid=7097)							4
    X=0	enter number(ppid=7095,pid=7097)							3
    X=0	enter number(ppid=7095,pid=7097)							2
    X=0	enter number(ppid=7095,pid=7097)							1
    
    
    pid=7097,pid2=7098(wait status=28416,r=7097)
    
    
    NO i!=5(pid=7095) for x=0
    
    X=1	enter number(ppid=7095,pid=7115)							5
    X=1	enter number(ppid=7095,pid=7115)							4
    X=1	enter number(ppid=7095,pid=7115)							3
    X=1	enter number(ppid=7095,pid=7115)							2
    X=1	enter number(ppid=7095,pid=7115)							1
    
    
    pid=7115,pid2=7116(wait status=28672,r=7115)
    
    
    NO i!=5(pid=7095) for x=1
    
    X=2	enter number(ppid=7095,pid=7141)							5
    X=2	enter number(ppid=7095,pid=7141)							4
    X=2	enter number(ppid=7095,pid=7141)							3
    X=2	enter number(ppid=7095,pid=7141)							2
    
    
    pid=7141,pid2=7142(wait status=28672,r=0) #why is r=0 when pid=7141,in this case?
    
    
    NO i!=5(pid=7095) for x=2
    
    THE END(pid=7095
    [c_d@localhost C scratchpad]$ X=2	enter number(ppid=1,pid=7141)							1 #orphaned yet again
    
    [c_d@localhost C scratchpad]$
    any ideas why the third time why return value of waitpid() was 0?
    Last edited by creeping death; 03-30-2009 at 07:24 AM.
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  4. #4
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    SUCCESS!!

    forgot to include<sys/wait.h>
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  5. #5
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    final code

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<signal.h>
    #include <sys/wait.h>
    #define CL system
    #define C "clear" 
    
    int main()
    {
        int x,i=0,pid,pid2,status;
        FILE *temp,*rf;         //temp will contain the marks,rf will contain if user gave an input or not
        temp=fopen("temp","w");
        fputc(0,temp);          //set marks to 0
        fputc(0,temp);
        fclose(temp);
        CL(C);                  //CL(C)=clear screen(see #define)
        for(x=0;x<3;x++)
        {
            CL(C);
            pid=-1;pid2=-1;
            if((pid=fork()) == 0)   //child process- the countdown timer
            {
                for(i=5;i>0;i--)    //start a 5 sec countdown
                {                   
                    CL(C);
                    printf("X=%d\tenter a number(ppid=%d,pid=%d)",x,getppid(),getpid());
                    printf("\t\t\t\t\t\t\t%d\a\n",i);
                    sleep(1);                                                                                     
                }
                exit(0);      //exit when 5 secs are over
            }
            else      //parent process
            {       
               if((pid2=fork()) == 0)   //create a seperate child process for input
               { 
                    int noattempts,nocorrect,rval;
                    rf=fopen("rval","w");   //set value in rval file to -1
                    fclose(rf);               
                    rval=scanf("%d",&i);
                    rf=fopen("rval","w");   
                    fputc(rval,rf);        //if scanf worked correctly then value in rval file will be 1
                    fclose(rf);
                    kill(pid,SIGKILL);     //when input is recieved kill the timer process
                    temp=fopen("temp","r");
                    noattempts=fgetc(temp);
                    nocorrect=fgetc(temp);
                    fclose(temp);
                    
                    if(i==5)               //check the user input 
                    {
                       printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);
                       noattempts++;
                       nocorrect++;                                   
                    }
                    else
                    {
                        printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);                
                        noattempts++;
                    }
                    temp=fopen("temp","w");
                    fputc(noattempts,temp);  //update marks
                    fputc(nocorrect,temp);
                    fclose(temp);                 
                    exit(0);        //exit the scanf process.no need to kill this if user entered input appropriately
               }                
               waitpid(pid,&status,0); //wait for child process...timer process.                                 
               rf=fopen("rval","r");
               if(fgetc(rf)!=1)   //check if user entered input appropriately
               {
                    printf("\nAppropriate input not specified\n");
                    kill(pid2,SIGKILL);   
               }
               fclose(rf);           
            }        
            printf("\n\nNext question...");
            fflush(stdout);
            sleep(3);           //take a deep breath
        }
        CL(C);
        temp=fopen("temp","r");
        printf("THE END(pid=%d)\nNo of Correct=%d\nNo of Attempts=%d\n",getpid(),fgetc(temp),fgetc(temp)); //this should be executed when all other child processes are over.
        fclose(temp);
        remove("temp");      //cleanup
        remove("rval");      
        return 0;    
    }
    it works nicely, but here i m using files, to "pass" values from one process to another. what other alternative do i have?
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  6. #6
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Memory-mapped file I/O?

    That's still using files, but could be a lot more efficient.

  7. #7
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    Quote Originally Posted by cyberfish View Post
    Memory-mapped file I/O?

    That's still using files, but could be a lot more efficient.
    any hyperlinks you could direct me to(please dont say google it or wiki it)
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  8. #8

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reaping zombies with sigaction()
    By heras in forum Linux Programming
    Replies: 4
    Last Post: 03-12-2008, 01:05 PM
  2. Zombies and Multiprocessor???
    By 3dkiwi in forum Linux Programming
    Replies: 5
    Last Post: 01-06-2007, 12:32 AM
  3. Fork => zombie => error
    By Morbo in forum Linux Programming
    Replies: 1
    Last Post: 12-08-2005, 11:53 AM