Perl的线程中断睡眠不行

问题描述:

我想明白了,因为如果我运行这段代码Perl的线程中断睡眠不行

#!/usr/bin/perl 
use strict; 
use warnings FATAL => 'all'; 

use threads; 
use threads::shared; 

sub mythread { 
    my $end = 0; # Thread termination variable 

    while(!$end) { 
     eval { 
      local $SIG{'ALRM'} = sub { 
       print "SIGALARM received\n"; 
       $end = 1; 
       die "Alarm!\n"; 
      }; 

      sleep(5); # Wait 
     }; 
     die [email protected] unless [email protected] eq "Alarm!\n"; 
    } 
} 

my $end = 0; # Main termination variable 
$SIG{'INT'} = sub { 
    $end = 1; # Set Main termination variable 
}; 

my $thr = threads->create(\&mythread); 
while(!$end) { 
    sleep(1); 
    print "1 second passed\n"; 
} 

print "Send SIGALARM to thread\n"; 
$thr->kill("SIGALRM"); 

print "Main Wait for thread end\n"; 
$thr->join(); 

如果我打CTRL-C,主线程正确地捕捉到信号,但是当发送到MyThread的睡眠信号没有终止,但等待5秒,即使我把代码包装在一个像Perldoc sleep eval这样说。

信号只能发送到进程,而不是线程。从$thread->kill的文档:

警告:本模块提供的线索信令能力实际上并没有通过OS发送信号。它在Perl级别模拟信号,以便在适当的线程中调用信号处理程序。例如,发送$thr->kill('STOP')实际上并不会挂起一个线程(或整个进程),但会导致在该线程中调用$SIG{'STOP'}处理程序(如上所述)。

操作系统不知道任何关于您的请求,所以您的sleep不会中断。


在这种情况下,你可以使用类似以下内容:

use Time::HiRes qw(); 

sub polling_sleep { 
    my ($dur) = @_; 
    my $until = Time::HiRes::time() + $dur; 
    while (1) { 
     $dur = $until - Time::HiRes::time(); 
     last if $dur < 0; 
     Time::HiRes::sleep($dur < 0.5 ? $dur : 0.5); 
    } 
} 

polling_sleep(5); 

有没有通用的解决方案。