【问题标题】:Fork and return without waiting for child in perl在 perl 中分叉并返回而不等待孩子
【发布时间】: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) 系统调用”可用。

标签: linux perl fork cgi


【解决方案1】:

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: $!";
    }

本文的其余部分解释了如何帮助用户跟踪正在运行的作业。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 2012-03-07
    • 2011-02-08
    • 2021-04-28
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多