由于某些原因,线程似乎无法找到$ SIG {' KILL')信号。我从这里的评论中得到了代码http://www.perlmonks.org/index.pl?node_id=557219这是在Windows上。
use strict;
use warnings;
use threads;
sub test_sub{
$SIG{'KILL'} = sub { threads->exit(); };
while(1){}
}
my $new_thread = threads->create('test_sub');
$new_thread->kill('KILL')->detach();
返回
Signal KILL received in thread 1, but no signal handler set. at test1.pl line 13.
Perl exited with active threads:
1 running and unjoined
0 finished and unjoined
0 running and detached
编辑:看起来我正在使用线程版本' 1.43'。我不知道问题是否存在,但我会尝试更新的版本。
答案 0 :(得分:2)
这似乎是某种竞争条件,当有更多事情发生时它会起作用。
use warnings;
use strict;
use feature 'say';
use threads;
use threads::shared;
my $thread_handler_on :shared = 0;
sub test_handler {
say "\tIn thread.";
$SIG{'KILL'} = sub {
$thread_handler_on = 1;
say "\tSet flag, exiting the thread in handler";
threads->exit();
};
sleep 3;
say "\tSet handler";
sleep 1;
say "\tHandler done napping";
}
my $new_thread = threads->create( 'test_handler' );
sleep 1;
say "Sending 'kill' to thread";
$new_thread->kill('KILL')->detach();
sleep 5;
say "Did handler run: $thread_handler_on";
问题中的代码是out of threads个文档(以及detach
)。
这打印
In thread. Sending 'kill' to thread Set flag, exiting the thread in handler Did handler run: 1
如果主线程中没有sleep
,我也会得到报告的行为。
请注意这些"信号"每个Threads signalling
通过内核发送该模块提供的线程信令功能实际上并不通过OS发送信号。它模拟Perl级别的信号,以便在适当的线程中调用信号处理程序。
答案 1 :(得分:2)
只有两种竞争条件可能会导致您观察到的行为:
您在孩子有机会设置信号处理程序之前发送了KILL信号。
下面,我使用同步来确保在发送信号之前创建信号处理程序。
您在信号处理程序有机会致电threads->exit
之前退出该计划。
为什么人们坚持使用->detach
?
修正:
use strict;
use warnings;
use feature qw( say );
use threads;
use threads::shared;
sub test_handler {
say sprintf "[%s %s] Starting thread", time, threads->tid;
say sprintf "[%s %s] Doing stuff", time, threads->tid;
sleep 4;
say sprintf "[%s %s] Done doing stuff", time, threads->tid;
say sprintf "[%s %s] Exiting thread", time, threads->tid;
}
sub create_thread(&) {
my ($thread_func) = @_;
# Reap any threads that might have exited.
$_->join() for threads->list(threads::joinable);
my $ready :shared = 0;
my $thread = async {
$SIG{KILL} = sub {
say sprintf "[%s %s] Forcibly exiting thread", time, threads->tid;
threads->exit();
};
# Signal creator that the thread is initialized.
{ lock $ready; $ready = 1; cond_signal($ready); }
$thread_func->();
};
# Wait for the thread to finish initializing.
{ lock $ready; while (!$ready) { cond_wait($ready); } }
return $thread;
}
my $thread = create_thread(\&test_handler);
say sprintf "[%s %s] Sending KILL signal", time, threads->tid;
$thread->kill('KILL');
say sprintf "[%s %s] Doing stuff", time, threads->tid;
sleep(2);
say sprintf "[%s %s] Done doing stuff", time, threads->tid;
# Wait for threads to exit.
say sprintf "[%s %s] Waiting for threads to exit", time, threads->tid;
$_->join() for threads->list();
say sprintf "[%s %s] Exiting", time, threads->tid;
输出:
[1513212149 1] Starting thread
[1513212149 1] Doing stuff
[1513212149 0] Sending KILL signal
[1513212149 0] Doing stuff
[1513212151 0] Done doing stuff
[1513212151 0] Waiting for threads to exit
[1513212153 1] Forcibly exiting thread
[1513212153 0] Exiting
重要请注意,信号不会中断sleep
。没有发送实际的POSIX信号 [1] (因为您只能将它们发送到进程),因此OS调用不会被中断。相反,Perl会主动检查大多数Perl操作码 [2] 之间是否发送了信号。但这意味着长时间运行的操作码如sleep
,m//
和XS函数调用可以无限期地延迟信号处理程序。