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);
有没有通用的解决方案。