【发布时间】:2018-05-14 13:41:27
【问题描述】:
我有一个使用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(它不工作的地方)以来,我还没有接触过代码。
【问题讨论】:
-
fork()是一个 POSIX 的东西,不应该在平台之间改变。我也很确定这两个平台都不会效仿它。您的问题可能是其他问题。我猜想在 Web 服务器或客户端上进行缓冲。 -
@Borodin 当 OP 谈论 Linux 的不同变体时,这是一个安全的假设。
-
@Sobrique:我同意,但我仍然认为你的评论非常笼统。无法保证人们会在上下文中阅读您的评论,我更喜欢 “在这些平台上不应该有所不同” 或 “不应该在不同的 Linux 风格之间改变”.
-
Re "似乎父母在等待长期运行的孩子完成后再返回",您是如何得出这个结论的?
-
Ubuntu 不会“模拟”
fork,而是fork“执行 fork(2) 系统调用以创建新进程... ”,因为“fork(2) 系统调用”可用。