c++ - fork() 之后如何处理 execvp(...) 错误?

标签 c++ linux posix exec fork

我做常规的事情:

  • fork()
  • execvp(cmd, ) 在 child 身上

如果 execvp 失败是因为没有找到 cmd,我如何在父进程中注意到这个错误?

最佳答案

众所周知self-pipe trick可以是adapted为此目的。

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <sysexits.h>
#include <unistd.h>

int main(int argc, char **argv) {
    int pipefds[2];
    int count, err;
    pid_t child;

    if (pipe(pipefds)) {
        perror("pipe");
        return EX_OSERR;
    }
    if (fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD) | FD_CLOEXEC)) {
        perror("fcntl");
        return EX_OSERR;
    }

    switch (child = fork()) {
    case -1:
        perror("fork");
        return EX_OSERR;
    case 0:
        close(pipefds[0]);
        execvp(argv[1], argv + 1);
        write(pipefds[1], &errno, sizeof(int));
        _exit(0);
    default:
        close(pipefds[1]);
        while ((count = read(pipefds[0], &err, sizeof(errno))) == -1)
            if (errno != EAGAIN && errno != EINTR) break;
        if (count) {
            fprintf(stderr, "child's execvp: %s\n", strerror(err));
            return EX_UNAVAILABLE;
        }
        close(pipefds[0]);
        puts("waiting for child...");
        while (waitpid(child, &err, 0) == -1)
            if (errno != EINTR) {
                perror("waitpid");
                return EX_SOFTWARE;
            }
        if (WIFEXITED(err))
            printf("child exited with %d\n", WEXITSTATUS(err));
        else if (WIFSIGNALED(err))
            printf("child killed by %d\n", WTERMSIG(err));
    }
    return err;
}

这是一个完整的程序。

$ ./a.out foo
child's execvp: No such file or directory
$ (sleep 1 && killall -QUIT sleep &); ./a.out sleep 60
waiting for child...
child killed by 3
$ ./a.out true
waiting for child...
child exited with 0

这是如何工作的:

创建一个管道,并使写入端点CLOEXEC:它会在成功执行exec 时自动关闭。

在 child 中,尝试exec。如果成功,我们将不再有控制权,但管道已关闭。如果失败,将失败代码写入管道并退出。

在父级中,尝试从另一个管道端点读取。如果 read 返回零,则管道已关闭并且子进程必须成功执行 exec。如果 read 返回数据,那就是我们 child 写的失败代码。

关于c++ - fork() 之后如何处理 execvp(...) 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1584956/

相关文章:

c++ - Cocos2D-X - 初始化 CCTMXTiledMap 时出现 EXC_BAD_ACCESS(代码=2,地址=0x0)

linux - 为什么命令 "perf report"什么都不显示?

linux - 串行通信 OSX 期间显示的奇怪字符

c - POSIX 保证写入磁盘

c - 在什么条件下管道读取是原子的?

c++ - boost::lexical_cast 从字符串到字符异常

c++ - 操作动态库加载的符号解析顺序

c++ - 从函数返回一个 std::Vector<object> 需要一个默认值

linux - R 2.15 在 Redhat 中安装

multithreading - POSIX命名信号量可以同步线程吗?