代码之家  ›  专栏  ›  技术社区  ›  psilouette

execv和fork:通知父级子级执行文件失败

  •  5
  • psilouette  · 技术社区  · 8 年前

    主进程如何知道子进程未能执行文件(例如,没有这样的文件或目录)?例如,在下面的代码中,如何让run()返回0以外的值?谢谢

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    enum ErrorType { noError, immediateFailure, returnFailure, forkFailure };
    
    using namespace std;
    
    int run(void)
    {
        int error = noError;
        //char proc[] = "/bin/uname";
        char proc[] = "/usr/bin/Idontexist";
        char *const params[] = {proc, NULL};
    
        pid_t pid = fork();
    
        printf("pid = %d\n",pid);
    
        if (pid == 0)
        {
            if ( execv(proc,params)==-1 )
            {
                error = immediateFailure;
            }
            printf("child: error = %d\n",error);
        }
        else if (pid > 0)
        {
            /*  This is the parent process
             *  incase you want to do something
             *  like wait for the child process to finish
             */
            int waitError;
            waitpid(pid, &waitError, 0);
    
            if ( waitError )
                error = returnFailure;
    
            printf("parent: error = %d, waitError = %d\n",error,waitError);
        }
        else
        {
            error = forkFailure;
        }
    
        return error;
    }
    
    int main(void)
    {
        printf("run() = %d\n",run());
    
        return 0;
    }
    

    输出:

    pid = 4286
    pid = 0
    child: error = 1
    run() = 1
    parent: error = 0, waitError = 0
    run() = 0
    
    4 回复  |  直到 8 年前
        1
  •  1
  •   Antti Haapala -- Слава Україні    5 年前

    您需要从返回错误代码 main exit() 使用值。现在你是 return 惯性导航与制导 0 从…起 主要的 在所有情况下,这将是父级从中接收的子级的退出代码 waitpid .

    最好的解决办法是添加 _exit(error) 在子进程中:

    printf("child: error = %d\n",error);
    _exit(error);
    

    在任何情况下,使用整数常量而不是随机枚举常量enum。1和2是许多unix命令的常见返回值,1表示命令不成功(例如 grep 没有找到任何匹配项),而2+表示命令确实失败(错误的参数或诸如此类)。

    bash , zsh 和其他外壳使用 127 作为退出代码发送信号 命令未找到/无法运行 ; 因此建议这样做:

    #define COMMAND_NOT_RUNNABLE 127
    
    /* ... */
    
    execv(proc, params);  // exec never returns if successful.
    perror(proc);
    _exit(COMMAND_NOT_RUNNABLE);
    

    使用的原因 _exit 在子进程中,它不会刷新stdio缓冲区(它也会存在于父进程中),并且不会运行 atexit 钩子。(谢谢 Andrew Henle )

        2
  •  1
  •   J. Scott Elblein roon    5 年前

    在我的情况下 exit(EXIT_FAILURE) 不要导致返回 waitpid() EXIT_FAILURE 子进程的状态,始终 0 .我的解决方案是 abort() 子进程,如果 execv() / execve() 无法执行。

        3
  •  0
  •   user3386109    8 年前

    问题是在 execv 失败。子集 error immediateFailure 并将其返回给 main 然后 主要的 打印错误号,并返回 0 但是 0 意味着成功,所以父进程认为子进程成功了。

    解决方案是从 主要的 ,或呼叫 exit 在子代码中,例如。

    if (pid == 0)
    {
        execv(proc,params);
        error = immediateFailure;
        printf("child: error = %d\n",error);
        exit( error );
    }
    

    请注意,您不需要从 执行 自从 执行 如果成功,将不会返回。它只会在失败时返回,并且总是返回-1。

        4
  •  0
  •   GMichael    8 年前

    除了建议的 exit(error); 你应该给出具体的选项 waitpid 。在我将呼叫更改为之前,您的代码对我无效 waitpid(pid, &waitError, WUNTRACED | WCONTINUED);