【问题标题】:What to do if exec() fails?如果 exec() 失败怎么办?
【发布时间】:2012-06-26 21:00:06
【问题描述】:

假设我们有一个代码做这样的事情:

int pipes[2];
pipe(pipes);
pid_t p = fork();
if(0 == p)
{
   dup2(pipes[1], STDOUT_FILENO);
   execv("/path/to/my/program", NULL);
   ...
}
else
{
//... parent process stuff
}

正如你所看到的,它正在创建一个管道,分叉并使用管道来读取子进程的输出(我不能在这里使用popen,因为我还需要子进程的 PID 用于其他目的)。

问题是,如果在上面的代码中,execv 失败了怎么办?我应该调用 exit() 还是 abort()?据我所知,这些函数关闭了打开的文件描述符。既然fork-ed进程继承了父进程的文件描述符,是不是意味着父进程使用的文件描述符会变得不可用?

UPD

我想强调的是,问题不在于 exec() 加载的可执行文件失败,而是 exec 本身,例如以防第一个参数引用的文件未找到或不可执行。

【问题讨论】:

  • 如果你不想要一个混乱的控制流,我建议 exit() 在失败的 exec 上使用已知的退出代码。
  • 大家好,但是如果exit() 也失败了怎么办?
  • 我不认为这应该是一个问题 - atexit 函数中发生的任何有趣的事情在最坏的情况下都会导致异常终止,否则我们无法控制它(退出永远不会返回)。

标签: c linux unix ipc fork


【解决方案1】:

您应该使用exit(int),因为父进程可以使用waitpid() 读取参数的(低字节)。这使您可以在父进程中适当地处理错误。根据您的程序的用途,您可能希望使用_exit 而不是exit。不同之处在于_exit 不会运行用atexit 注册的函数,也不会刷新stdio 流。

【讨论】:

    【解决方案2】:

    execv() 失败的原因大约有十几个,您可能希望以不同的方式处理每一个。

    子失败不会影响父文件描述符。实际上,它们是引用计数的。

    【讨论】:

      【解决方案3】:

      您应该致电_exit()。它完成了exit() 所做的一切,但它避免调用任何已注册的atexit() 函数。调用_exit() 意味着家长将能够获取您失败的孩子的退出状态,并采取任何必要的步骤。

      【讨论】:

        猜你喜欢
        • 2011-04-26
        • 2019-02-10
        • 2011-06-14
        • 2012-08-01
        • 1970-01-01
        • 2010-12-31
        • 2016-01-11
        • 2021-12-22
        • 1970-01-01
        相关资源
        最近更新 更多