Multithreading Perl和curses库-从子线程退出

Multithreading Perl和curses库-从子线程退出,multithreading,perl,ncurses,Multithreading,Perl,Ncurses,然后我做了ps-fumyuserid 我看到,$myexe仍在运行 Q1)如何强制子进程退出?threads->exit()似乎不起作用示例程序最明显的问题是它对curses库使用了多个线程。那不行。(诅咒不是线程安全的)。如果必须这样做,请将所有诅咒保持在同一个线程中。您调用退出,但不要分离或加入线程 棍子: Perl exited with active threads: 1 running and unjoined 0 finished and unjoin

然后我做了
ps-fumyuserid

我看到,
$myexe
仍在运行


Q1)如何强制子进程退出?threads->exit()似乎不起作用

示例程序最明显的问题是它对curses库使用了多个线程。那不行。(诅咒不是线程安全的)。如果必须这样做,请将所有诅咒保持在同一个线程中。

您调用
退出
,但不要
分离
加入
线程

棍子:

Perl exited with active threads:
        1 running and unjoined
        0 finished and unjoined
        0 running and detached
最后,您的“主”代码将等待线程(全部)退出

但是-
threads->exit()
用于退出当前线程。见:

为了终止另一个线程,您需要类似于
threads->kill
的东西。发送一个“正确的”终止信号,或使用信号处理程序处理
SIGUSR1
或类似信号

不过,我可能会有点不同的做法-定义一个共享变量:

foreach my $thr ( threads -> list() ) { 
    $thr -> join;
}
然后在while循环中对其进行测试,这样您就有了一个正常的执行流,而不是一个中途的
kill

您的
kill(INT,$$)
将终止您的主进程,只需将线程放到地板上。那真的不是好风格

所以,回溯一下,我认为,您遇到的问题是,perl中的“信号”并不是您所期望的。Perl使用安全信号,这使得阻塞调用(例如从文件句柄读取)阻塞信号

所以我通常不会建议在线程中使用信号是个好主意——它们有点不稳定,这对程序的可预测性不好

通过在线程中定义信号处理程序,可以“抛出”和“捕获”信号:

my $done : shared; 
然后使用以下方法“调用”它:

 $SIG{'USR1'} = sub { print "Caught USR1"; die };
但在某些情况下,这不会像你预期的那样立即“纾困”

例如,这将起作用:

 $worker -> kill ( 'USR1' );
但是如果您的while循环正在读取文件句柄-这是一个阻塞调用,因此“kill”将一直保持到阻塞解除为止

例如


所有的诅咒工作都在同一个线程中。至少写入屏幕部分。它发生在进程输出子例程中$myexe只提供了一堆行。它不起任何作用。而父线程刚刚读取键盘输入我的评论主要是关于Q2(屏幕混乱)。如果不调用endwin,curses甚至不会尝试恢复终端模式——听起来就像症状一样。然而,Q1似乎表示该分支甚至可能没有被调用。在阅读脚本时,有些细节似乎被省略了,因此很难进一步分析。如何强制子线程立即退出?似乎子线程没有得到SIGINT信号
threads->kill
应该这样做。但我想建议您创建一个共享变量,并在while循环中测试它。如果打开一个exec句柄,您可以使用该句柄返回的pid作为终止对象。好的,我想我得到了一些东西-基本上-如果您从
main
线程终止
open
的结果,那么您的while循环
break
。请参见代码中的示例。
 $worker -> kill ( 'USR1' );
#!/usr/bin/perl

use strict;
use warnings;

use threads;

sub worker {

   print Dumper \%SIG;
   my $tail_pid = open ( my $tail_proc, "-|", "tail -f /var/log/messages" );
   $SIG{'USR1'} = sub { print "Caught USR1\nKilling $tail_pid"; kill ( 'TERM', $tail_pid ); die; threads -> exit() };

   print "Pre-loop\n";

   while ( 1 ) {
       print "Thread processing\n";
    sleep 1;
   }
    print "Done";
   return;
}

my $worker = threads -> create ( \&worker );

sleep 2;
print "Sending kill\n";
$worker -> kill ( 'SIGUSR1' );
sleep 2;
print "waiting for join\n";

$worker -> join();
while ( <$tail_proc> ) {
#!/usr/bin/perl

use strict;
use warnings;

use threads;
use threads::shared;

my $kill_pid : shared;

sub worker {
   $kill_pid = open ( my $tail_proc, "-|", "tail -f /var/log/messages" );
   print "Pre-loop\n";
   while ( <$tail_proc> ) {
       print "Thread processing\n";
       print;
    sleep 1;
   }
    print "Done";
   return;
}

my $worker = threads -> create ( \&worker );

sleep 2;
print "Sending kill\n";

if ( defined $kill_pid ) { print "killing tail, $kill_pid\n"; kill ( 'TERM', $kill_pid ); };
sleep 2;
print "waiting for join\n";

$worker -> join();