我有一个使用fork()
启动子进程的perl CGI程序。孩子进行一些长时间运行(约60秒)的计算,最终将结果保存在tmp文件中。父节点应该将控制权返回给浏览器,浏览器显示进度消息并定期检查子节点是否已写入其tmp文件;文件出现后,将显示结果。所以代码看起来像这样:
# Get a unique name for this job
my $guid = Data::GUID->new;
my $id = $guid->as_hex;
# Do the fork
my $pid = fork;
if (!defined $pid) {
die "cannot fork: $!";
# Child does this
} elsif ($pid == 0) {
# Do some calculations
# Save results in a filename with $id
# Parent does this
} else {
# Return the location of the tmp files to the client
return "Content-Type: text/html\n\n", $id;
# Browser uses contents of $id to check for the result file
}
我最初在RedHat Linux上设置它,它运行得很好。但是,现在我正在尝试将它移植到运行Ubuntu的服务器上,并且看起来父进程在等待长时间运行的子进程返回之前。我相信这是因为浏览器在计算期间挂起,从不显示进度页面,并在计算完成后立即跳转到结果。
我怀疑这与fork仿真有关,但我不确定,而且我无法找到解决方法。谢谢你的任何建议。
编辑:这段代码是子程序的一部分 - 我使用CGI :: Application,因此调用代码只是“使用”这段代码。因此返回声明。我怀疑这会解决这个问题,因为我从没有触及代码,因为从Red Hat(它工作的地方)移植到Linux(它没有)。
答案 0 :(得分:0)
Randal Schwartz的Watching long processes through CGI提供了一个有用的例子。分叉是直截了当的:
if ( my $pid = fork ) { # parent does
delete_all(); # clear parameters
param( 'session', $session );
print redirect( self_url() );
}
elsif ( defined $pid ) { # child does
close STDOUT; # so parent can go on
unless ( open F, "-|" ) {
open STDERR, ">&=1";
exec "/usr/sbin/traceroute", $host;
die "Cannot execute traceroute: $!";
}
本文的其余部分介绍了如何帮助用户跟踪正在运行的作业。