【问题标题】:Why is "kill" is not exiting a thread immediately?为什么“kill”没有立即退出线程?
【发布时间】:2022-07-08 02:03:38
【问题描述】:

我正在尝试编写一个简单的脚本来生成一个执行可能超时的任务的线程。 (为了给 StackOverflow 写一个简单的例子,我用sleep 命令替换了实际过程)。

这个程序产生一个线程,然后使用cond_timedwait 来监视线程并检查它是否超时。如果发生超时,它会调用线程上的kill 方法并使用“STOP”信号通知线程它应该退出。

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

问题是,即使检测到超时并将“STOP”信号发送到线程,程序似乎仍在等待整整 10 秒,然后才打印“Stop signal received”并退出。

我尝试更改它,使其在终止线程后调用detach 而不是join,但是从未打印过“收到停止信号”消息,这意味着程序在线程干净退出之前退出。我想确保线程实际上被中断并退出,因为在实际程序中,我想在超时发生后杀死并重试该进程,如果已经在分离线程上运行另一个实例,该进程将无法工作.

我怎样才能使线程在收到“STOP”信号时立即打印消息并退出?

【问题讨论】:

    标签: windows multithreading perl timeout signals


    【解决方案1】:

    这些“信号”并不是真正的操作系统信号,而且有(很多?)操作它们不会中断。

    CAVEAT:此模块提供的线程信号功能实际上并不通过操作系统发送信号。它在 Perl 级别模拟信号,以便在适当的线程中调用信号处理程序。例如,发送$thr->kill('STOP') 并不会真正挂起线程(或整个进程),但会导致在该线程中调用$SIG{'STOP'} 处理程序(如上所示)。

    因此,通常不适合在kill() 命令中使用的信号(例如,kill('KILL', $$)) 可以与->kill() 方法一起使用(同样,如上所示)。

    相应地,向线程发送信号不会中断线程当前正在执行的操作:信号将在当前操作完成后执行。例如,如果线程卡在 I/O 调用上,向其发送信号不会导致 I/O 调用中断,从而立即执行信号。

    sleep 似乎是不可中断的,因为它适用于不同的耗时操作。简化

    use warnings;
    use strict;
    use feature 'say';
    
    use threads;
    
    say "Start at ", scalar localtime, " (", time, ")";
    
    my $thread = threads->create(sub {
        $|=1;
        # Tell the thread how to handle the STOP signal
        $SIG{'STOP'} = sub {
            say "\tIn thread, Stop signal received. Exiting at ", time;
            threads->exit();
        };
    
        say "\t--> In the thread ", threads->self->tid;
    
        # Perform a process that takes some time
        #sleep 10;
        do { sleep 1; say "\tnappin'... ($_ sec)" } for 1..10;
    });
    
    sleep 3;
    $thread->kill('STOP')->join();  # works with detach() as well, albeit differently
    
    say "Main thread done, exiting at ", time;
    

    【讨论】:

      猜你喜欢
      • 2012-01-30
      • 2011-04-20
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多