【发布时间】:2019-11-19 05:44:27
【问题描述】:
我已经使用 Perl 线程设置了一个多线程应用程序,并试图检测线程内的超时(线程应该经历几个可能超时的系统调用,我需要知道它何时停止)。
我尝试使用 alarm() 并遇到了由 thread0 而不是触发警报的线程接收的警报信号的有据可查的问题。所以我开始使用 Alarm::Concurrent。
use threads ('yield',
'stack_size' => 64*4096,
'exit' => 'threads_only',
'stringify');
use Alarm::Concurrent qw(setalarm clearalarm);
threads->create(\&MyThreadFunc,1);
threads->create(\&MyThreadFunc,1);
threads->create(\&MyThreadFunc,5);
threads->create(\&MyThreadFunc,5);
sub MyThreadFunc {
my $result = "Never Ran";
my $timeToSleep = $_[0];
my $tid = threads->tid();
eval {
setalarm 3, sub { die "Timedout\n" };
sleep ($timeToSleep);
clearalarm;
$result = "TID $tid EXITED\n";
};
if ($@ eq "Timedout\n")
{
$result = "TID $tid TIMED OUT\n";
}
elsif ($@)
{
$result = "$@";
}
print "Thread returning $result";
return $result;
}
while (scalar threads::list(threads::running))
{
foreach my $thread (threads->list(threads::joinable)) { $thread->join(); }
}
我的预期:
我希望线程 TID 1 和 2 正常退出,线程 3 和 4 采用 TimedOut 路径(因为会调用警报并且 eval() 会捕获骰子“Timedout\n”。相反,它们都采用了已退出路径。
Thread returning TID 1 EXITED
Thread returning TID 2 EXITED
Thread returning TID 4 EXITED
Thread returning TID 3 EXITED
【问题讨论】:
-
另见Perl threads with alarm 并根据Threads and ALARM() - There is a solution or workaround?
alarm使用信号(发送到进程而不是线程),因此它不适用于线程 -
如果您的用例有more suitable option,当然,另一种选择是避免使用线程。
-
对 cmets 和答案假设的明确声明:我认为这个模块不能跨线程工作;查看源代码——它只记录(调度)“正常”警报。其名称中的“并发”是指它能够在同一个程序中拥有多个警报(我们不能使用内置的
alarm)。要么使用解决方法(如在 Håkon 的回答中),要么使用其他方式来保持时间或其他工具(如分叉、事件)。 -
(上面的“同一程序中的多个警报”是指同时,“同时”)