FastCGI、Perl和Exit

FastCGI、Perl和Exit,perl,fastcgi,psgi,Perl,Fastcgi,Psgi,在过去的几周里,我一直在磨砺一个大型的、有几十年历史的代码库的性能,在这里,有人建议我应该看看FastCGI或HTTP::Engine之类的东西。我发现使用FastCGI非常简单,但有一个问题我发现答案参差不齐 我读过的一些文档说,对于通过FastCGI运行的脚本,永远不应该调用exit,因为这会损害持久加载脚本的整个概念。其他人说这无关紧要。我的代码在很多地方都使用exit,在这些地方确保没有任何东西继续执行是很重要的。例如,我有调用授权检查的受限访问组件: use MyCode::Autho

在过去的几周里,我一直在磨砺一个大型的、有几十年历史的代码库的性能,在这里,有人建议我应该看看FastCGI或HTTP::Engine之类的东西。我发现使用FastCGI非常简单,但有一个问题我发现答案参差不齐

我读过的一些文档说,对于通过FastCGI运行的脚本,永远不应该调用
exit
,因为这会损害持久加载脚本的整个概念。其他人说这无关紧要。我的代码在很多地方都使用exit,在这些地方确保没有任何东西继续执行是很重要的。例如,我有调用授权检查的受限访问组件:

use MyCode::Authorization;
our $authorization = MyCode::Authorization->new();

sub administration {
    $authorization->checkCredentials();

    #...Do restricted access stuff.
}
为了尽可能避免代码中出现错误,允许某人在不应该访问这些函数的情况下访问这些函数,
checkCredentials
在通过登录页面生成用户友好的响应(如果答案是用户没有适当的凭据),然后使用exit()结束该过程。例如:

sub checkCredentials {
   #Logic to check credentials

   if ($validCredential) {
       return 1;
   }
   else {
       # Build web response.
       # Then:
       exit;
   }
}
}

我使用了它,这样我就不会不小心忽略了一些导致安全漏洞的东西。目前,如果提供了正确的凭据,调用例程可以安全地假定它只能从
checkCredentials
中恢复控制

但是,我想知道是否需要删除这些调用以充分利用FastCGI。FCGI的
$req->Finish()
(或PSGI中HTTP::Engine的等效版本)是否足以替代

我读过一篇文章,说你不应该在通过FastCGI运行的脚本上调用exit

您不希望进程退出,因为使用FastCGI的目的是使用单个进程来处理多个请求(以避免加载时间等)

因此,您要做的是覆盖exit,以便结束特定于请求的代码,而不是FastCGI请求循环


您可以覆盖退出,但必须在编译时这样做。因此,使用一个标志来表示超越是否处于活动状态

我们的$override\u exit=0;
开始{
*核心::全局::退出=子(;$){
如果$OVERRIDE\u EXIT,则禁用“EXIT\u OVERRIDE\n”;
CORE::exit($\u0]//0);
};
}
while(get_request()){
#其他设置。。。
评估{
本地$override_exit=1;
处理请求();
};
我的$exit\u被调用=$@eq“exit\u覆盖\n”;
如果调用了$@&!$exit,则记录错误($@);
如果调用了$Exit,\u,则记录\u错误(“调用Exit\n”);
#其他清理。。。
}
但这会创建一个可能被无意中捕获的异常。因此,让我们使用
last

我们的$override\u exit=0;
开始{
*核心::全局::退出=子(;$){
无警告qw(退出);
如果$OVERRIDE\u EXIT,则上次退出\u OVERRIDE;
CORE::exit($\u0]//0);
};
}
while(get_request()){
#其他设置。。。
我的$exit_被称为=1;
退出超控:{
本地$override_exit=1;
eval{handle_request()};
如果$@,则记录错误($@);
$exit_被调用=0;
}
如果调用了$Exit,\u,则记录\u错误(“调用Exit\n”);
#其他清理。。。
}

这确实是一段很酷的代码,尽管我对替代方案仍有点不确定,也就是说,链接到“重复”问题堆栈溢出注释并没有完全触及我的困惑点。如果我覆盖
退出
,如何确保相同的等价项?例如,该处理不会继续,但在FastCGI处理的情况下,我立即返回阻塞
,而
循环等待另一个请求。我重新打开了它,但使用替代方案没有意义,因为您应该已经在使用它。等价什么?如果您问“如果我覆盖退出,如何确保我立即返回阻塞while循环以等待另一个请求。等价物?”,这正是答案告诉您的方法。抱歉,我不清楚这一点。所以handle_request()部分确保我回到while循环?哦,我想我应该提到
{…}
(作为一个语句,而不是散列构造函数)在技术上是一个循环。在文档(IIRC)中称为“裸循环”,它是一个只执行一次的循环。因此,
last
只需退出该循环即可。(标签处理嵌套。)答案与