У меня есть функция в C, которая создает дочерний процесс и использует execvp() для выполнения определенной задачи.
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;
Как видите, если задача не удалась, содержащий ее процесс следует удалить, а функция вернет значение ERROR.
Я пытался реализовать эту функциональность с помощью exit(-1) (а также _exit()), но оператор возврата никогда не достигается, поскольку код находится в зоне родительского процесса. Кроме того, если я удалю exit() и позволю функции вернуть ошибку, процесс продолжит существовать и будет мешать работе программы. Как я могу завершить созданный дочерний процесс до того, как функция вернется в случае сбоя задачи execvp?
Родительский процесс должен использовать wait() или waitpid() или друзей, чтобы получить статус выхода дочернего процесса.





процесс, содержащий его, должен быть удален, а функция возвращается со значением
ERROR.
Нет, этого не происходит. Успешный fork() создает новый процесс и возвращается 0 к этому новому процессу. В вашем примере в этом новом процессе выполняется execvp, и в случае сбоя вы немедленно выполняете exit(-1);, после чего процесс завершается, и линия return ERROR; никогда не будет достигнута.
Вы можете получить статус завершения дочернего процесса в родительском процессе, используя wait или waitpid. Используйте WIFEXITED/WEXITSTATUS, WIFSIGNALED/WTERMSIG, WIFSTOPPED/WSTOPSIG и WIFCONTINUED, чтобы распаковать информацию о том, как он вышел (или остановился/продолжил).
Пример:
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);
}
Примечание. Функция _exit() похожа на exit(), но не вызывает никаких функций, зарегистрированных с помощью atexit() или on_exit(), и вы, вероятно, не захотите, чтобы они вызывались только потому, что execvp не удалось.
Когда дочерний процесс создается с помощью fork(), он наследует копии регистраций своего родительского on_exit. При успешном вызове одной из функций exec() (например, execvp) все регистрации удаляются.
«но оператор возврата никогда не достигается, поскольку код находится в зоне родительского процесса». Нет, это не так.
return ERROR;не достигается, потому что он происходит сразу после вызоваexit, после чего дочерний процесс перестает существовать. Непонятно, почему вы думаете, что вам нужно что-то убивать. Просто удалитеreturn ERROR;.