2017-07-27 58 views
6

考虑下面的代码:在execl()调用之后退出(0)是否有意义?

close(channel_data->pty_master); 

if (login_tty(channel_data->pty_slave) != 0) // new terminal session 
{ 
    exit(1); // fail 
} 

execl("/bin/sh", "sh", mode, command, NULL); // replace process image 
exit(0); 

execl()文档,当前的进程映像被替换和呼叫仅返回上的错误。

但是,如果过程映像被替换,为什么在致电execl()之后致电exit()

回答

3

在某些exec(3)函数之后调用exit是合理的,因为它们可能会失败(例如,当execve(2)失败时)。 execve(2)页面列出了一些故障原因。

最好是exit(EXIT_FAILURE)或其他一些(非0)退出代码(传统上使用127或126这样的高退出代码来分隔exec的故障与它运行的程序中的错误),我建议在exit之前拨打perror。由于explained by PSKocick有很好的理由叫_exit(但他的论点可以颠倒,人们会想运行atexit和标准fflush通过使用exit代替)。

在你的情况下,失败的可能性不大,但不过想象一下,如果一些其他进程已取消/bin/sh(例如系统管理员使运行在根目录/bin/rm -rf .,或/bin/,也许在一些其他的终端窗口的愚蠢的错误)。

仍然是execve也可以当系统资源失败(暂时的)枯竭,e.g为

ENOMEM没有足够的内核内存可用。

而且(在极少数情况下)这可能发生在/bin/sh;

顺便说一句,您的exec用法可能会失败(与E2BIG)如果(由于错误)command是一百万个非空字节的字符串。

作为一般编码规则,应检查所有重要的system calls与失败。

+0

在这种情况下,“失败”究竟意味着什么? – Shuzheng

+0

这意味着您尝试运行的程序无法启动,例如如果/ bin/sh不存在,或者它没有适当的执行权限,或者系统不允许你运行程序(例如,你遇到了一些系统限制或策略,不允许你创建更多的进程 – nos

+1

@Shuzheng'exec()'family函数可能会失败,原因很多,但结果是一样的:当前进程的图像不会被替换,并且会设置'errno',因此代码放在'exec * ()'call will be executed。 – Geographer

1

但是,如果在过程映像被替换后调用execl()后为什么调用exit()?

正如你所说,execl()只在错误的回报:

execl("/bin/sh", "sh", mode, command, NULL); // replace process image 
exit(0); 

在上面的代码,exit()被称为只有在execl()调用失败。


由于Jonathan Leffler suggested in his comment它可能是一个非常好的主意,返回其它的值大于,因为零表示成功和代码确实失败如果程序的控制流曾达到的exit()通话在上面的代码中。

+1

0的退出状态表示'成功' - 但代码失败 –

4

执行调用可能失败。一个常见的结语是:

perror("Some eror message"); 
_exit(127); /*or _exit(1); (127 is what shells return) */ 

你通常会运行_exit而非exit这里,以跳过atexit挂钩和stdio缓冲区刷新。

+0

*'一个普通的结语将会是* * - 我认为这就是为什么在代码中使用注释来解释技术是不好的风格,请记住,有时候这肯定会被复制;) – Wolf

3

您会想拨exit,因为您没有对exec程序提出疑问,而且您通常不希望该进程因为没有运行您希望运行的程序而停留。由于execl仅在失败时返回,因此无需检查退货状态。

在很多情况下,打印错误消息以查明失败原因也很有意义。您还应该使用非0的退出代码。非零退出代码用于指示异常退出,并且父进程在调用wait时可以捕获该代码。

execl("/bin/sh", "sh", mode, command, NULL); 
perror("command failed"); 
exit(1); 

所以,是的,是有意义的CAL exit,但不一定exit(0)

相关问题