请考虑以下代码:
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()
的文档,当前的过程映像正在被替换,并且调用仅在错误时返回。
但是,如果更换过程映像,为什么在调用exit()
后调用execl()
?
答案 0 :(得分:4)
执行电话可能会失败。一个常见的结局将是:
var nearbyOrganizations = _UoW.OrganisationRepo.All.ToList()
.Select(x => new
{ //use an anonymous type or any type you want
Org = x,
Distance = new GeoCoordinate(x.Latitude, x.Longitude).GetDistanceTo(userLocation)
}) //it's probably outside EF's SQL generation step by now, but you could add one more .Select here that does the math if it fails (return the GeoCoordinate object)
.Where(x=> x.Distance < radius)
.ToList();
您通常会在此处运行perror("Some eror message");
_exit(127); /*or _exit(1); (127 is what shells return) */
而不是_exit
,以便跳过exit
挂钩和atexit
缓冲区刷新。
答案 1 :(得分:3)
在某些exec(3)函数之后调用exit
是有意义的,因为它们可能会失败(例如execve(2)失败时)。 execve(2)页面列出了许多失败原因。
最好是exit(EXIT_FAILURE)
或其他一些(非0)退出代码(通常会使用127或126这样的高退出代码来分隔exec
与错误的错误它将运行的程序),我建议在perror
之前调用exit
。由于explained by PSKocick有充分的理由可以调用_exit
(但他的论点可能会被颠倒,人们希望通过使用atexit
运行exit
和标准fflushs。
在你的情况下,失败是不太可能的,但是想象一下,如果某个其他进程已经删除/bin/sh
(例如,系统管理员在根目录中运行/bin/rm -rf .
时犯了愚蠢的错误,或者{{1或许在其他终端窗口中)。
当系统资源(暂时)耗尽时,/bin/
也可能失败,例如
execve
内核内存不足。
并且(在极少数情况下)这可能发生在ENOMEM
;
/bin/sh
是一百万个非空字节的字符串,那么你的exec
用法可能会失败(使用E2BIG
)。
作为一般编码规则,应检查所有重要的system calls是否失败。
答案 2 :(得分:3)
您需要致电RewriteEngine On
RewriteRule ^test-([0-9]+) test.php?id=$1
,因为您未能exit
该问题的程序,并且您通常不希望该进程因为未运行您希望运行的程序而闲置。由于exec
仅在失败时返回,因此无需检查返回状态。
在许多情况下,打印错误消息以查看失败原因也是有意义的。您还应该使用0以外的退出代码。非零退出代码用于指示异常退出,父进程可以在调用execl
时捕获该代码。
wait
所以是的,cal execl("/bin/sh", "sh", mode, command, NULL);
perror("command failed");
exit(1);
是有意义的,但不一定是exit
。
答案 3 :(得分: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()
调用,则 。