Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using waitpid to run process in background?

Tags:

c

process

waitpid

I am trying to mimic the bash feature of running process in the background if "&" is found at the end of the command. I have the following function...and I don't think it's doing what I want it to do

int execute(char* args[],int background,int *cstatus){
    pid_t   child;
    pid_t   ch;                         /*Pid of child returned by wait*/
    if ((child = fork()) == 0){                 /*Child Process*/
        execvp(args[0],args);       
        fprintf(stderr, "RSI: %s: command not found\n",args[0]); /*If execvp failes*/
        exit(1);

    }else{          /*Parent process*/
        if (child== (pid_t)(-1)) {
            fprintf(stderr,"Fork failed\n"); exit(1);
        }else{
            if (background==0){             /*If not running in background..wait for process to finish*/
                ch = wait(cstatus);
            }else{
                printf("%ld Started\n",(long)getpid());
        /*  printf("Parent: Child %ld exited with status = %ld\n", (long) ch, (long)cstatus);
    */  }}
    }
return 0;
}
int wait_and_poll(int *cstatus){
    pid_t status;
    status = waitpid(-1,cstatus,WNOHANG);
    if (status>0){
        fprintf(stdout,"%ld Terminated.\n",(long) status);
    }
return 0;
}

If i just run "ls -l " it works as expected..but if I want to run ls in the background..and have the program keep accepting new commands I call the function with background flag set as 1 and I want it to run the process in the background, tell me that it has created the process..and then prompt to accept next command.

like image 389
user1411893 Avatar asked Jan 27 '13 14:01

user1411893


2 Answers

I don't think waitpid(-1, &cstatus, WNOHANG); does what you think it does. You need to check its return value. If it is > 0, that's the PID of the child process that has exited. If it's 0 or -1, no child process has changed state.

You can just call waitpid(-1, &cstatus, WNOHANG); before and/or after each command you run. Call it in a loop to catch more than one child exit.

You can also handle SIGCHILD. Your process will receive this signal immediately after a child exit, which is good if you want to report child process termination immediately, without waiting for user's input.

like image 150
n. 1.8e9-where's-my-share m. Avatar answered Sep 19 '22 14:09

n. 1.8e9-where's-my-share m.


That is simple. Consider you have a process P with id pid.

If you want it to run in the background(which can be recognized by & at the end of your input string to the shell/program ), you should do this

//some code
id=fork();
if(id==0)
{
//child does work here
}
else
{
//Parent does work here
if(!strcmp(last string,"&")==0)waitpid(id,&status,0);
}

Thus the parent does not wait if you request for background execution, else it waits.

like image 25
Aakash Anuj Avatar answered Sep 20 '22 14:09

Aakash Anuj