为什么“杀人”不是立即退出线程吗?
我正在尝试编写一个简单的脚本,该脚本催生了执行可能超时任务的线程。 (为了编写一个简单的stackoverflow示例,我用sleep
命令代替了实际过程)。
该程序产生线程,然后使用cond_timedwait
监视线程并检查是否已计时。如果发生超时,它将用“停止”信号在线程上调用kill
方法,以通知线程应退出的线程。
use strict;
use threads;
use threads::shared;
use warnings;
my $var :shared;
my $thread = threads->create(sub {
# Tell the thread how to handle the STOP signal
local $SIG{'STOP'} = sub {
print "Stop signal received\n";
threads->exit();
};
# Perform a process that takes some time
sleep 10;
# Signal that the thread is complete
lock($var); cond_signal($var);
});
# Current time + 1 second
my $wait_time = time() + 1;
my $timeout;
{
# Wait for the thread to complete or until a timeout has occurred
lock($var); $timeout = !cond_timedwait($var, $wait_time);
}
# Check if a timeout occurred
if ($timeout) {
print "A timeout has occurred\n";
# Signal the thread to stop
$thread->kill('STOP')->join();
}
else {
$thread->join();
}
该代码成功运行并打印以下输出:
1秒钟...
A timeout has occurred
9秒通过...
Stop signal received
问题是,即使检测到超时并将“停止”信号发送到线程,该程序似乎仍然是等待整个10秒钟,然后打印“收到的停止信号”并退出。
我尝试更改它,以便调用分离
,而不是join
杀死线程后,但是从未打印过“停止信号”消息,这意味着该程序正在退出线程干净退出。我想确保该线程实际上被中断并退出,因为在实际程序中,我将要在超时发生后杀死和重试该过程,并且如果已经在独立线程上运行另一个实例,则该过程将无法工作。
我该如何使线程立即打印消息并在接收“停止”信号时退出?
I am trying to write a simple script that spawns a thread that performs a task that may timeout. (For the sake of writing a simple example for StackOverflow I replaced the actual process with a sleep
command).
This program spawns a thread and then uses a cond_timedwait
to monitor the thread and check if it has timed out. If a timeout occurs it calls the kill
method on the thread with a "STOP" signal to notify the thread that it should exit.
use strict;
use threads;
use threads::shared;
use warnings;
my $var :shared;
my $thread = threads->create(sub {
# Tell the thread how to handle the STOP signal
local $SIG{'STOP'} = sub {
print "Stop signal received\n";
threads->exit();
};
# Perform a process that takes some time
sleep 10;
# Signal that the thread is complete
lock($var); cond_signal($var);
});
# Current time + 1 second
my $wait_time = time() + 1;
my $timeout;
{
# Wait for the thread to complete or until a timeout has occurred
lock($var); $timeout = !cond_timedwait($var, $wait_time);
}
# Check if a timeout occurred
if ($timeout) {
print "A timeout has occurred\n";
# Signal the thread to stop
$thread->kill('STOP')->join();
}
else {
$thread->join();
}
This code runs successfully and prints the following output:
1 second passes...
A timeout has occurred
9 seconds pass...
Stop signal received
The problem is, even though a timeout is detected and the "STOP" signal is sent to the thread, the program still seems to be waiting the full 10 seconds before printing "Stop signal received" and exiting.
I tried changing it so it calls detach
instead of join
after killing the thread, but then the "Stop signal received" message is never printed which means the program is exiting before the thread cleanly exits. I want to make sure the thread is actually interrupted and exits, because in the real program I will want to kill and retry the process after the timeout has occurred and the process won't work if there is another instance already running on a detached thread.
How can I make it so the thread instantly prints the message and exits when it receives the "STOP" signal?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些“信号” 不是实际的操作信号,他们赢得了操作'打断
“ 操作”的粒度尚未陈述,但是
睡眠
显然是不间断的,因此信号处理程序仅在完成后才运行。有了不同的作业,可以用分离
而不是JOIN
中断输出
,它仍然会在正确的时间停止该循环,但我没有迹象表明信号处理程序运行。 (在我的测试中,我有信号处理程序还编写一个文件,并使用
分离
否。)它对我来说都可以使用共享变量等,就像在问题中一样。这个
睡眠
当然并不重要 - 但是,请仔细测试信号旨在停止的实际作业。These "signals" aren't the actual OS signals, and there are operations they won't interrupt
The granularity of what the "operation" is isn't stated but
sleep
is clearly uninterruptable so the signal handler runs only after it completes. With a different job to interruptOutput
With
detach
instead ofjoin
it still stops that loop at the right time but I see no indication that a signal handler ran. (In my tests I have the signal handler also write a file and withdetach
it doesn't.) It all works the same for me with a shared variable etc, like in the question.This
sleep
doesn't matter of course -- but it is all a warning to carefully test with actual jobs that the signal is aimed to stop.信号只能发送到进程。因此,
$ thread-> kill('stop')
不可能发送实际信号。因此,没有任何中断睡眠
。在每个语句之间,Perl检查是否有“信号”。如果有信号,则可以处理。因此,仅一旦
睡眠
完成才能完成“信号”。如果您有十秒钟的睡眠,而不是十秒钟的睡眠,那么等待最多将是一秒钟。
Signals can only be sent to processes. As such,
$thread->kill('STOP')
can't possibly be sending an actual signal. As such, nothing interruptssleep
.Between each statement, Perl checks if a "signal" came in. If it has, it handles it. So the "signal" is only handled once
sleep
completes.If you had ten one second sleeps instead of one ten second sleep, the wait would be at most one second.