【问题标题】:Perl: Error handling threadsPerl:错误处理线程
【发布时间】:2015-03-26 14:03:08
【问题描述】:
sub worker {
    exit 1;
}

my $thr = threads->create(\&worker);    
while ($thr->is_running()) {
    print "running\n";
}
my $rc = $thr->join();
exit $rc;

我来自 Python。有没有类似于尝试/除了我可以在while($thr->is_running)附近使用的东西@

我得到(因为我在工人中退出 1):

Perl exited with active threads:
0 running and unjoined
1 finished and unjoined       
0 running and detached                                                                                      

我希望能够捕捉出口或其他编译错误工人可能有

use strict;
use warnings;
use threads;

sub worker {
    my $bad = 1/0;
}

my $thr = threads->create( \&worker );
while ( $thr->is_running() ) {
    sleep 1;
}
my $rc = $thr->join();  #NB - RC will be 'undef' because there's no return.

输出:

Thread 1 terminated abnormally: Illegal division by zero at mythread.pl line 6.

是否有可能捕获它的错误?以及如何以及在哪里?

【问题讨论】:

  • 为什么你的线程需要退出?您应该使用return 退出线程。
  • @AKHolland 这是一个示例,因此我可以显示错误。如果我把 $a= 0 (没有我的或其他东西它会做同样的事情)。关键是我想捕捉我可能在线程中看到的任何错误
  • 编译错误完全不同。如果脚本无法完整编译,则根本不会运行。此外,您还为 $a = 0 选择了一个不好的例子,它是唯一可以在没有 my 的情况下正常工作的变量之一。
  • @AKHolland 无论如何。不是问题的重点。我希望能够处理工作线程内可能发生的任何错误
  • 如果您有编译错误,它将不会运行线程(或其他任何东西)。所以,是的,这就是重点。任何正常错误 (die "bleeeh") 都不需要特殊处理。

标签: multithreading perl


【解决方案1】:
  • 不要在你的线程中调用exit。这将退出您的整个程序。 threads -> exit 是你想要的。

http://perldoc.perl.org/threads.html#EXITING-A-THREAD

线程->exit()

如果需要,可以通过调用 threads->exit() 随时退出线程。这将导致线程在标量上下文中返回 undef,或者在列表上下文中返回空列表。 从主线程调用时,它的行为与 exit(0) 相同。

  • join 等待线程完成。

  • 不要使用$a。无论如何,这是一个糟糕的变量名,但它也用于 perl 排序。

  • 您正在捕获$rc,但这意味着您的线程中有return。因为它,它将是未定义的。

但这会起作用:

use strict;
use warnings;
use threads;

sub worker {
    sleep 10;
    threads->exit;
}

my $thr = threads->create( \&worker );
while ( $thr->is_running() ) {
    print $thr ->tid, " running\n";
    sleep 1;
}
print $thr ->tid, " not running\n";
sleep 5;
my $rc = $thr->join();  #NB - RC will be 'undef' because there's no return.

在后一种情况下,$rcundef,因为您 exited。如果要捕获异常退出,可以测试它是否未定义。 (只要确保你确实在成功时返回了一些东西)。

或者,使用eval 将您的代码包装在线程中,因为这不会是致命错误。不会经常出现,但我建议不要尝试捕获广泛的可能致命错误,而只是测试它是否成功完成会好得多。

回答你的第二个问题 - 像这样:

use strict;
use warnings;
use threads;

sub worker {
    sleep 5;
    my $fatal = 1 / 0;
    return 1;
}

sub otherworker {
    sleep 4;
    eval { my $fatal = 1 / 0; };
    if   ($@) { return $@ }
    else      { return "No error" }
}

my $thr  = threads->create( \&worker );
my $thr2 = threads->create( \&otherworker );

while ( $thr->is_running() ) {
    print $thr ->tid, " running\n";
    sleep 1;
}
print $thr ->tid, " not running\n";

foreach my $thread ( threads->list ) {
    my $return_code = $thread->join;
    if ( not defined $return_code ) {
        print $thread ->tid(), ": terminated abnormally\n";
    }
    else {
        print $thread ->tid, ": exited with $return_code \n";
    }
}

【讨论】:

  • 我做了你的测试,我有一个问题。这是我刚刚发布的原始问题的一部分
  • 用插图修改答案。
  • "不要在你的线程中调用 exit。这会退出你的整个程序。线程 -> exit 是你想要的。"为了完整起见,应该注意您可以use threads 'exit' => 'threads_only',它将指示线程任何exit 都将被视为仅结束线程而不是整个程序。见perl doc for more information
猜你喜欢
  • 2013-08-16
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多