Perl FCGI不死退出 [英] Perl FCGI Exit Without Dieing

查看:79
本文介绍了Perl FCGI不死退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果使用Perl FCGI,如何在不使用exit的情况下结束脚本.搜索几天后,我发现的唯一解决方案是跳转到主脚本中的label.下面是主要index.fcgi的代码.

How to end script without using using exit if using Perl FCGI. After searching for days the only solution I found is to jump at label in the main script. below is the code of the main index.fcgi.

    $fcgi_requests = 0; # the number of requests this fcgi process handled.
$handling_request = 0;
$exit_requested = 0;
$app_quit_request = 0; # End the application but not the FCGI process

# workaround for known bug in libfcgi
while (($ignore) = each %ENV) { }

$fcgi_request = FCGI::Request();
#$fcgi_request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket);

sub sig_handler {
    my ($callpackage, $callfile, $callline) = caller;
    if ($app_quit_request) {
        $app_quit_request = 0;
        goto ABORTLABEL;
    }

    $exit_requested = 1;
    exit(0) if !$handling_request;
}

$SIG{USR1} = \&sig_handler;
$SIG{TERM} = \&sig_handler;
$SIG{PIPE} = 'IGNORE';

#The goal of fast cgi is to load the program once, and iterate in a loop for every request.
while ($handling_request = ($fcgi_request->Accept() >= 0)) {
    process_fcgi_request();
    $handling_request = 0;
    last if $exit_requested;
    #exit if -M $ENV{SCRIPT_FILENAME} < 0; # Autorestart
}

$fcgi_request->Finish();
exit(0);
#=========================================================#
sub process_fcgi_request() {
    $fcgi_requests++;

    # dispatch current request
    my_app();

    $fcgi_request->Finish();
}
#=========================================================#
# let it think we are done, used by abort
ABORTLABEL:
    $fcgi_request->Finish();
#=========================================================#

主要请求是我想从可能由长深度调用的子insidi模块内部停止程序执行,例如在accounts模块中的登录功能内部. 当然我不能使用exit,因为它将终止fcgi进程,我尝试了所有错误并抛出并尝试了所有模块都使用die的方法,这也结束了进程.当然,我可以使用每个子项的返回值,但这需要为fcgi重写整个程序.

The main request is I want to stop the program execution from inside sub insidi modules that may be called by long depth for example inside a login function in a accounts module. Of course I can not use exit because it will terminate the fcgi process, I tried all error and throw and try modules all use die which also ends the process. Of course I can use the return from each sub but this will require to rewrite the whole program for fcgi.

推荐答案

在Perl中对异常建模的正常方法是在eval BLOCK中调用die,它捕获了die,因此不会终止该过程.它只会终止eval并且程序从此之后立即继续运行.据我所知,CPAN上的异常处理模块主要是对该基本功能的包装,以使其具有不同的语法或使编写catch块更容易.因此,我很惊讶这些对您不起作用.您实际上是尝试过它们还是只是假设die总是会杀死进程?这个名称有点误导,因为它实际上意味着抛出异常".就像您在eval之外执行此操作一样,解释器会捕获它,并且它唯一的响应就是终止该过程.

The normal way to model exceptions in Perl is to call die inside eval BLOCK, which catches the die and so doesn't terminate the process. It'll just terminate the eval and the program continues to run from immediately afterwards. As far as I've seen, the exception-handling modules on CPAN are mostly wrappers around this basic functionality to give it different syntax or make it easier to write catch blocks. Therefore I'm surprised these don't work for you. Did you actually try them or did you just assume die always kills the process? The name is slightly misleading, because it really means 'throw an exception'. Just if you do that outside an eval the interpreter catches it, and its only response is to terminate the process.

eval {
  say "Hello world";
  die;
  say "Not printed";
};
say "Is printed";

但是,您不想在eval内部调用exit.没什么.

You don't want to call exit inside an eval though. Nothing catches that.

我建议尽管重写FCGI的整个控制流程.代码的生命周期发生了显着变化,因此您必须进行一定数量的修改,以确保变量重用工作正常并且不会泄漏内存.通常,最好先进行此操作,而不要花几天时间来追踪奇怪的错误.

I would recommend though rewriting the entire control flow for FCGI. The lifecycle of your code changes significantly, so you have to make a certain amount of modifications to make sure that variable re-use is working properly and you're not leaking memory. Often it's better to do that up front rather than spend days tracking down odd bugs later.

这篇关于Perl FCGI不死退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆