use threads;
use threads::shared;
use Term::ReadKey;
sub input_worker {
local $SIG{'KILL'} = sub { threads->exit(0); return;};
while (1) {
if (defined(my $char = ReadKey 0, *STDIN)) {
print "$char";
}
}
return;
} ## end sub input_worker
my $in_thr = threads->create(\&input_worker);
sleep 5;
my $rc = $in_thr->kill('KILL')->join();
print "$rc\n";
这个程序不会自行退出而只是挂起。 它只会在按下“输入”后退出
我怎样才能使它在'kill'信号发出后自行退出
P.S。我不想使用detach();
答案 0 :(得分:5)
混合信号和线程是一个挑战,因为$thread->kill
实际上并不使用真实信号(因为信号被发送到进程,而不是线程)。这也是一样,因为如果确实如此,SIGKILL
可能会破坏事物。
即使谈论'正常'信号 - 你也会有轻微的意外行为,因为perl对它们的处理请参见:perlipc
。使用并非不可能,但您需要了解所涉及的警告。
但问题的根源是 - 信号是安全处理的,这意味着perl会等待一段合适的时间来处理它。在“读取”操作期间不会这样做,因此信号处理将被推迟。
我认为这里可能发生的事情是ReadKey
不像您认为的那样是非阻塞操作。参考Term::ReadKey
联机帮助页
ReadKey MODE [,Filehandle] 采用整数参数,该参数当前可以是以下值之一:
0 Perform a normal read using getc
-1 Perform a non-blocked read
>0 Perform a timed read
所以它的作用是 - 从STDIN
开始读取,并阻止(忽略信号)直到你按下回车键。此时它运行您的信号处理程序。
鉴于你在这里尝试做什么 - 我建议你根本不想使用信号,而只是使用共享变量。
这样的事情:
use threads;
use threads::shared;
use Term::ReadKey;
my $done : shared;
sub input_worker {
while ( not $done ) {
if ( defined( my $char = ReadKey( -1, *STDIN ) ) ) {
print "$char";
}
}
return;
} ## end sub input_worker
my $in_thr = threads->create( \&input_worker );
sleep 10;
$done++;
my $rc = $in_thr->join();
print "$rc\n";
将在超时后终止,并且因为它正在执行非阻塞读取,它将按时保释,无需输入。你应该注意 - 这个线程将“旋转”快速循环,等待输入是否被按下 - 所以它的CPU效率不高。 (循环中的一个小延迟对那里有很大帮助,比如0.1s)。