Kill child process when execvp fails in C function

60 Views Asked by At

I have a function in C that creates a child process and uses execvp() to execute a certain task.

pid_t pid = fork();
if (pid == 0) {
  if (execvp(cmd->arg_array[0], cmd->arg_array) == -1) {
    exit(-1);
    return ERROR;
  }
} else if (pid < 0)
  return ERROR;

//Some more code...
return NO_ERROR;

As you can see, if the task fails, the process containing it should be deleted and the function returned with ERROR value.

I tried implementing this functionality with an exit(-1) (and _exit() also), but the return statement is never reached, since the code is in the parent process zone. Also, if I remove the exit() and let the function return the error, the process keeps existing and interferes with the program functioning. How can I kill the created child process before the function returns when execvp task fails?

1

There are 1 best solutions below

0
Ted Lyngmo On BEST ANSWER

the process containing it should be deleted and the function returned with ERROR value.

No, that's not what happens. A successful fork() creates a new process and returns 0 to this new process. In you example, execvp is executed in this new process and if it fails, you immediately do exit(-1);, at which point the process terminates and the line return ERROR; will never be reached.

You can collect the child's exit status in the parent process by using wait or waitpid. Use WIFEXITED/WEXITSTATUS, WIFSIGNALED/WTERMSIG, WIFSTOPPED/WSTOPSIG and WIFCONTINUED to unpack the information about how it exited (or stopped/continued).

Example:

pid_t pid = fork();

if (pid == 0) {
    execvp(cmd->arg_array[0], cmd->arg_array);
    // there's no need to check the return value from execvp:
    // if execvp returns, it means that it failed.
    _exit(1); // use _exit() instead of exit() to abort when exec fails
} else if (pid == -1)
    return ERROR;
}

// parent
int wstatus;
pid_t child;

while( (child = wait(&wstatus)) != -1 ) {
    printf("child %ld died with status %d\n", (long)child, wstatus);
}

Note: The function _exit() is like exit(), but does not call any functions registered with atexit() or on_exit() and you probably wouldn't want those to be called just because execvp failed.

When a child process is created via fork(), it inherits copies of its parent's on_exit registrations. Upon a successful call to one of the exec() functions (like execvp), all registrations are removed.