简体   繁体   English

在调用execl()之后退出(0)是否有意义?

[英]Does it make sense to exit(0) after a call to execl()?

Consider the following code: 请考虑以下代码:

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);

According to the documentation of execl() , the current process image is being replaced and the call returns only on errors. 根据execl()的文档,当前的进程映像正在被替换,并且调用仅在错误时返回。

But why call exit() after a call to execl() if the process image is replaced? 但是,如果更换过程映像,为什么在调用execl() exit()之后调用exit()

Exec calls may fail. Exec调用可能会失败。 A common epilogue would be: 一个常见的结局是:

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

You would usually run _exit rather than exit here, in order to skip atexit hooks and stdio buffer flushes. 你通常会运行_exit而不是在这里exit ,以便跳过atexit hooks和stdio buffer fllushes。

It does make sense to call exit after some exec(3) function because they can fail (eg when execve(2) is failing). 在某些exec(3)函数之后调用exit是有意义的,因为它们可能会失败(例如,当execve(2)失败时)。 The execve(2) page lists a number of failure reasons. execve(2)页面列出了许多失败原因。

It should better be exit(EXIT_FAILURE) or some other (non 0) exit code (conventionally a high exit code like 127 or 126 would be used for that usage, to separate failure of exec vs errors in the program it would run), and I recommend calling perror just before that exit . 最好是exit(EXIT_FAILURE)或其他一些(非0)退出代码(通常会使用127或126这样的高退出代码来分隔exec与它运行的程序中的错误),以及我建议在exit之前调用perror As explained by PSKocick there are good reasons to call _exit (but his arguments could be reversed, one would want to run atexit and standard fflushs by using exit instead). 正如PSKocick解释的那样 ,有很好的理由可以调用_exit (但是他的论点可以颠倒过来,人们希望通过使用exit来运行atexit和标准fflush)。

In your case, failure is unlikely, but imagine however if some other process has removed /bin/sh (eg the sysadmin making the stupid mistake of running /bin/rm -rf . in the root directory, or in /bin/ , perhaps in some other terminal window). 在你的情况下,失败是不太可能的,但想象一下,如果其他进程已经删除/bin/sh (例如,sysadmin在根目录中或在/bin/中运行/bin/rm -rf .犯了愚蠢的错误,也许在其他一些终端窗口)。

Still that execve could also fail when system resources are (temporarily) exhausted, eg for 当系统资源(暂时)耗尽时,该execve也可能失败,例如

ENOMEM Insufficient kernel memory was available. ENOMEM内核内存不足。

And (in rare cases) this could even happen for /bin/sh ; 并且(在极少数情况下)这甚至可能发生在/bin/sh ;

BTW your exec usage would probably fail (with E2BIG ) if (by mistake) command was a string of a million of non-null bytes. 如果(错误地) command是一百万个非空字节的字符串, E2BIG你的exec使用可能会失败(使用E2BIG )。

As a general coding rule, all important system calls should be checked against failure. 作为通用编码规则,应检查所有重要的系统调用以防止失败。

You'll want to call exit because you failed to exec the program in question and you typically don't want that process to hang around since it's not running what you wanted it to run. 你会想要调用exit因为你没有exec有问题的程序,而且你通常不希望这个过程因为它没有运行你想要它运行的东西而挂起。 Since execl only returns on failure, there's no need to check the return status. 由于execl仅在失败时返回,因此无需检查返回状态。

In many cases, it also makes sense to print an error message to see why it failed. 在许多情况下,打印错误消息以查看失败原因也是有意义的。 You should also use an exit code other than 0. A non-zero exit code is used to indicate an abnormal exit, and the parent process can capture that when it calls wait . 您还应该使用0以外的退出代码。非零退出代码用于指示异常退出,父进程可以在调用wait时捕获它。

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

So yes, it makes sense to cal exit , but not necessarily exit(0) . 所以是的,cal exit是有意义的,但不一定exit(0)

But why call exit() after a call to execl() if the process image is replaced? 但是,如果更换过程映像,为什么在调用execl()之后调用exit()?

As you said, execl() returns only on errors: 正如您所说, execl()仅返回错误:

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

In the code above, exit() is called only if the execl() call failed. 在上面的代码中,仅当execl()调用失败时才调用exit()


As Jonathan Leffler suggested in his comment it may be a very good idea to return a value other than zero , since zero indicates success and the code did indeed fail if the program's control flow ever reached the exit() call in the code above. 正如Jonathan Leffler在他的评论中建议的那样 ,返回以外的值可能是一个非常好的主意,因为零表示成功 ,如果程序的控制流在上面的代码中达到了exit()调用,则代码确实失败了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM