perl警报未按预期工作

时间:2012-10-16 18:52:58

标签: perl cgi alarms

我有一个简单的perl脚本,它调用一个shell脚本,当从浏览器调用时它总是“挂起”。我只想在20秒后强制暂停一下。当我在命令行中运行它时没有问题。但是当我从浏览器执行此操作时,脚本将被执行,但永远不会完成加载。所以我没有得到页面上的输出。如果我在命令行中删除-9进程,浏览器将完成加载,内容将显示在浏览器中。

我做了很多研究,似乎Web服务器正在等待shell脚本完成,因为shell脚本仍然具有标准输出的打开文件句柄。

这是我的代码。

#!/usr/bin/perl

use strict;
use warnings;

use CGI;

my $q = new CGI;

print $q->header;

my $timeout = 10;
my $pid = fork;

if ( defined $pid ) {
     if ( $pid ) {

         # this is the parent process
         local $SIG{ALRM} = sub { die "TIMEOUT" };

         alarm 10;

         # wait until child returns or timeout occurs    
         eval {
             waitpid( $pid, 0 );
         };

         alarm 0;

         if ( $@ && $@ =~ m/TIMEOUT/ ) {
            # timeout, kill the child process
            kill 9, $pid;
         }
    }
    else {
         # this is the child process
         # this call will never return. Note the use of exec instead of system
         exec "/opt/bea/domains/fsa/scripts/start.sh";
    }
}
else {
     die "Could not fork.";
}

在一段时间后,无论shell脚本的状态如何,如何强制页面完成加载。

1 个答案:

答案 0 :(得分:0)

问题是,在脚本完成后,webserver仍在等待创建的所有子项(甚至由您创建)完成。如何处理它的最佳方法是使用setsid创建单独的流程组。或者你甚至可以尝试“double fork trick”,你在那里分叉,从孩子那里再来一次。之后,如果init,第一个孩子将退出,第二个孩子将成为孩子。还要确保(在两种情况下)孩子都这样做:

close STDIN;
close STDOUT;
close STDERR;