Ankush K
Ankush K

Reputation: 332

wait(NULL) is not waiting till forked process is finished

This is the function that executes commands in a child process using system(). But once command completes execution it is expected to stop. Yet, on running ps command, I find new a.out process running. The program was supposed to wait for child to complete.

    void execute(char **argv)
    {
      if(fork() == 0)
      {
         if (argv[1] == NULL)
         {
           system(argv[0]);
         }
         else
         {
           char tmp[1024] ; 
           *(tmp+0) = '\0';
           strcat(tmp,*argv++);
           while(*argv !=NULL)
           {
              strcat(tmp," ");
              strcat(tmp,*argv++);
           }
           system(tmp);
         }
     }
    else
    {
        printf("\nWaiting\n");
        wait(0);
        printf("\nWaiting Complete\n");
    }
  }

The output for following is of this kind

SillyShell> ps

Waiting
  PID TTY          TIME CMD
 7520 tty2     00:00:00 bash
 7919 tty2     00:00:00 a.out
 7923 tty2     00:00:00 a.out
 7926 tty2     00:00:00 a.out
 7927 tty2     00:00:00 sh
 7928 tty2     00:00:00 ps
SillyShell>

This is the edited code as one of solution. Once the command with "&" is used after that again wait stops waiting for any process

            void execute(char **argv)
            {
                pid_t pid;
                int countArg = 0;
                char** tmp = argv;
                while(*argv !=NULL)
                {
                        *argv++;
                        countArg++;
                }
                argv = tmp;
                //printf("%s",argv[countArg-1]);

                int flg = 0;
                if(strcmp(argv[countArg-1], "&") == 0)
                {
                    //printf("Running in Background\n");
                    flg = 1;
                    argv[countArg-1] = NULL;
                }

                if((pid=fork()) < 0)
                {
                    printf("Could not create child process");
                    exit(1);
                }
                else if(pid == 0)
                {
                    if (execvp(*argv, argv) < 0)
                    {
                        printf("Could not execute command");
                        exit(2);
                    }
                else
                {
                    if(flg==1)
                        exit(0);
                }
                }
                else
                {
                    if(flg == 1)
                    {
                        printf("PID=%d Running in background\n",pid);
                        flg=0;
                    fflush(stdin);
                        return;
                    }
                else
                {

                    printf("Waiting %s %d",*argv,pid);
                    wait(NULL);
                    printf("--wait complete");
                }
                }
            }

Output

        Waiting clear 6532--wait completeSillyShell> ls
        a.out  blockchain  key.pem  task1.c  task3.c  wait.c
        bash   fork.c      OpenMP   task2.c  task4.c
        Waiting ls 6535--wait completeSillyShell> ps &
        PID=6537 Running in background
        SillyShell>    PID TTY          TIME CMD
        6406 pts/1    00:00:00 bash
        6531 pts/1    00:00:00 a.out
        6537 pts/1    00:00:00 ps

        SillyShell> ps
        Waiting ps 6538--wait completeSillyShell>    PID TTY          TIME CMD
        6406 pts/1    00:00:00 bash
        6531 pts/1    00:00:00 a.out
        6538 pts/1    00:00:00 ps

Upvotes: 0

Views: 1308

Answers (2)

Ankush K
Ankush K

Reputation: 332

Explicitly mentioning pid using waitpid(pid, status, option) solved all the issues.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409136

Your child process never exits! When the system function is done, then the child process will just continue. You need to explicitly exit it.

Or do like most shell-like implementations do and use the exec family of function to execute the command instead of system. The exec functions replace the process with the executed program, and never returns (unless there's an error). When the executed program terminates, that terminates the process as well.

Upvotes: 1

Related Questions