让我们看看,发生了什么:
my ($timeout, $size, $buffer) = (10, 10, undef);
eval {
#establish ALRM signal handler
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
#send alarm signal to program in 10 second
alarm $timeout;
#try yo read 10 bytes of data into $buffer
my $nread = sysread STDIN, $buffer, $size;
#cancel the previous timer without starting a new one
#if we returned from sysread. Yes, if 10 seconds pass
#before the next function is executed, the script will
#die even though the data was read
alarm 0;
#print number of bytes read (will be 10) and the string,
#read from input
print "$nread: $buffer";
};
如果要评估的字符串没有编译,或者在评估期间执行的 Perl 代码 die()d,则设置 $@。在这些情况下,$@ 的值是编译错误,或者是要死的参数:
if ($@) {
warn $@;
}
因此,如果我们在 10 秒内没有从 sysread 返回,这将打印出消息“alarm\n”。
在极不可能的情况下,当输入将在 10 秒过去之前收到并且我们将无法运行警报 0;,我建议使用以下代码:
my ($timeout, $size, $buffer) = (10, 10, undef);
#I define $nread before the signal handler as undef, so if it's defined
#it means, that sysread was executed and the value was assigned
my $nread = undef;
eval {
local $SIG{ALRM} = sub {
#if it's not defined - it means, that sysread wasn't executed
unless(defined($nread))
{
die "alarm\n";
}
};
alarm $timeout;
$nread = sysread STDIN, $buffer, $size;
alarm 0;
print "$nread: $buffer";
};
不幸的是,当赋值运算符没有被执行时,它并没有让我们摆脱这种情况。
链接:
http://perldoc.perl.org/functions/alarm.html
http://perldoc.perl.org/perlvar.html
http://perldoc.perl.org/functions/sysread.html