警报转义Perl'eval'块 [英] alarm Escaping Perl 'eval' block

查看:129
本文介绍了警报转义Perl'eval'块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Perl脚本,可以自动从各种来源下载内容.它使用alarmeval块中进行下载,因此如果花费的时间太长,尝试将超时:

I have a Perl script that automatically downloads content from various sources. It does the downloading in an eval block with an alarm so that the attempt will time out if it takes too long:

eval {
    alarm(5);
    my $res = $ua->request($req);
    $status = $res->is_success;
    $rawContent = $res->content;    
    $httpCode = $res->code;
    alarm(0);       
};

这已经工作了多年,但是在进行了一些系统更新后,突然间它停止了工作.相反,它遇到的第一个源超时,我收到以下错误,程序终止:

This has worked for years, but after doing some system updates, all of a sudden it quit working. Instead, the first source it hits that times out, I get the following error and the program terminates:

 Alarm clock

我做错了什么,导致阻止eval突然捕获警报?

What am I doing incorrectly that is preventing eval from catching the alarm all of a sudden?

推荐答案

SIGALRM的默认设置是终止程序,因此您需要对其进行处理.常见的方法是在捕获SIGALRM时发出die并将其转换为eval -ed的异常.

The default for SIGALRM is to terminate the program, so you need to handle it. A common way is to issue a die when SIGALRM is caught, turning it into an exception, which is 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

来自 perlipc

信号处理还用于Unix中的超时,在eval{}块中受到安全保护的同时,您设置了一个信号处理程序以捕获警报信号,然后计划在几秒钟内将信号发送给您.然后尝试阻止操作,在完成警报后清除警报,但在退出eval{}阻止之前清除警报.如果不成功,您将使用die()跳出该块,就像使用其他语言中的longjmp()或throw()一样.

Signal handling is also used for timeouts in Unix, While safely protected within an eval{} block, you set a signal handler to trap alarm signals and then schedule to have one delivered to you in some number of seconds. Then try your blocking operation, clearing the alarm when it’s done but not before you’ve exited your eval{} block. If it goes off, you’ll use die() to jump out of the block, much as you might using longjmp() or throw() in other languages.


关于它的工作方式,我能想到的一件事是,在eval中使用的程序包具有基于alarm的自己的计时器,从而取消了alarm.来自 alarm


As for how it ever worked, the one thing I can think of is that packages used inside eval had their own timers, based on alarm, thus canceling your alarm. From alarm

一次只能计数一个计时器.每次调用都会禁用前一个计时器,并且可以提供参数0来取消前一个计时器而无需启动新的计时器.

Only one timer may be counting at once. Each call disables the previous timer, and an argument of 0 may be supplied to cancel the previous timer without starting a new one.

超时时,它们可能引发了异常,并且您具有预期的行为.此软件包的行为在更新中已更改,现在您的警报可以正常工作并需要处理.当然,这是一个猜测.

They may have thrown exceptions when timing out and you had the expected behavior. This package behavior changed in the update and now your alarm works and needs handling. This is a guess, of course.

这篇关于警报转义Perl'eval'块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆