我有一个 Perl 脚本,可以自动从各种来源下载内容。它在一个eval
块与alarm
这样,如果时间太长,尝试就会超时:
eval {
alarm(5);
my $res = $ua->request($req);
$status = $res->is_success;
$rawContent = $res->content;
$httpCode = $res->code;
alarm(0);
};
这已经工作了很多年,但是在进行了一些系统更新之后,突然就不再工作了。相反,它命中的第一个源超时,我收到以下错误并且程序终止:
Alarm clock
我做错了什么阻碍了eval
突然接到警报?
SIGALRM默认是终止程序,所以需要处理它。一种常见的方式是发出die
当 SIGALRM 被捕获时,将其转为异常,即eval
-ed.
eval {
local $SIG{ALRM} = sub { die "Timed out" };
alarm(5);
my $res = $ua->request($req);
$status = $res->is_success;
$rawContent = $res->content;
$httpCode = $res->code;
alarm(0);
};
if ($@ and $@ !~ /Timed out/) { die } # re-raise if it is other error
From 信号输入perlipc
信号处理也用于 Unix 中的超时,同时在内部安全地受到保护eval{}
块,您设置一个信号处理程序来捕获警报信号,然后安排在几秒钟内将警报信号发送给您。然后尝试您的阻止操作,在完成后清除警报,但在退出之前不要清除警报。eval{}
堵塞。如果它发生了,您将使用 die() 跳出块,就像在其他语言中使用 longjmp() 或 throw() 一样。
至于它是如何工作的,我能想到的一件事是里面使用的包eval
有自己的计时器,基于alarm
,从而取消您的alarm
. From alarm
一次只能有一个计时器在计时。每次调用都会禁用前一个计时器,并且可以提供参数 0 来取消前一个计时器而不启动新的计时器。
他们可能在超时时抛出异常,而您却有预期的行为。此包行为在更新中发生了变化,现在您的警报可以工作并需要处理。当然,这只是猜测。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)