【问题标题】:How to create interrupt after x seconds in Perl?如何在 Perl 中 x 秒后创建中断?
【发布时间】:2018-11-01 11:41:04
【问题描述】:

让我用代码示例解释一下任务:

#!/usr/bin/perl
use strict;
use warnings;

my $t = 3;

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    print "Start $t\n";
    alarm(10);
    sleep($t);  # instead of this I have some data that collect code
    alarm(0);
    print "done with $t\n";
};

if ($@) {
    die unless $@ eq "alarm\n";
    print "timeout\n";
}

我有一些将数据推送到数组的代码,而不是sleep。数组将保证在`x 秒内被所需数据填充。

问题:如何在x秒后打印数组,而不使用sleep(非阻塞方式)?

据我所知,在 perl 中设置计时器的最简单方法是使用$SIG{ALRM}。但是如果我不需要计时器(不能使用sleep)怎么办,我只需要设置一个必须在预定义的秒数后运行的中断?也许我应该使用SIGINT 来完成这项任务?

任何帮助表示赞赏。

【问题讨论】:

  • 你能澄清一下吗?如果您将 sleep 替换为实际的数据收集代码,您的代码示例会出现什么错误?
  • 我认为您的代码目前的问题是您收集数据(睡眠)仅 3 秒。您将警报超时设置为 10 秒。因此,在睡眠 3 秒后,您会清除警报,因此您将永远不会触发它。我喜欢@ikegami 的解决方案

标签: perl timer interrupt


【解决方案1】:

要创建自己的中断,您需要两个执行线程。一种方法是启动一个子进程,该子进程将在满足某些条件时向其父进程发出信号。

$SIG{USR1} = \&code_to_run_after_interrupt;
my $ppid = $$;          # process id of parent
if (fork() == 0) {
    # child process
    sleep 15;
    kill 'USR1', $ppid;
    exit;
}
... main execution thread

在调用fork 15 秒后,您的主脚本将停止正在执行的操作,在名为code_to_run_after_interrupt 的子例程中执行代码,然后恢复主线程的执行。

(我在这里使用SIGUSR1,因为处理SIGINT可能会让你无法使用Ctrl-C来停止你的程序)

【讨论】:

    【解决方案2】:

    这就是alarm 的全部意义所在!只需使用更合适的信号处理程序即可。

    my @x;
    
    $SIG{ALRM} = sub {
       print("$_\n") for @x;
       $SIG{ALRM} = undef;
    };
    
    alarm(10);
    
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 2015-08-11
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多