2016-07-22 111 views
1

我正在使用Thread::Suspend从远程模块启动线程。部分$subrotine通话时间超过30秒。Perl线程不会暂停/恢复

my $thr = threads->create(sub { 
    capture(EXIT_ANY, $^X, $pathToModule, $subroutine, %arguments) 
}); 
return $thr->tid(); 

我的问题是我无法暂停/恢复创建的线程。下面是代码执行挂起线程:

use IPC::System::Simple qw (capture $EXITVAL EXIT_ANY); 
use threads; 
use Thread::Suspend; 
use Try::Tiny; 

sub suspendThread { 
    my $msg; 
    my $threadNumber = shift; 

    foreach (threads->list()) { 
     if ($_->tid() == $threadNumber) { 
      if ($_->is_suspended() == 0) { 
       try { 
        # here the execution of the thread is not paused 
        threads->suspend($_); 
       } catch { 
        print "error: " . $! . "\n"; 
       }; 

       $msg = "Process $threadNumber paused"; 
      } else { 
       $msg = "Process $threadNumber has to be resumed\n"; 
      } 
     } 
    } 

    return $msg; 
} 

这是从模块的代码,我动态地加载:

sub run { 
    no strict 'refs'; 
    my $funcRef = shift; 
    my %paramsRef = @_; 
    print &$funcRef(%paramsRef); 
} 

run(@ARGV); 

我猜测,问题是,sub传递到胎面构造函数调用捕获(从IPC::System::Simple模块)。我也试图用my $thr = threads->create(capture(EXIT_ANY, $^X, $pathToModule, $subroutine, %arguments));创建线程任何想法如何解决它。

+0

你想完成什么?为什么不使用例如信号量或其他IPC暂停线程? – Sobrique

+0

当您“不能暂停/恢复创建的线程”时会发生什么?你看到_error_打印了吗?什么是'$ msg'?由于'capture()'至少创建了一个子进程,因此您期望在父进程中挂起一个线程对子进程有什么影响? – pilcrow

+0

提示:'$ _-> suspend()'看起来比'threads-> suspend($ _)更古怪' – ikegami

回答

2

这些都是你的线程:

Parent process     Process launched by capture 
+---------------------+   +---------------------+ 
|      |   |      | 
| Main thread  |   | Main thread  | 
| +---------------+ |   | +---------------+ | 
| |    | |   | |    | | 
| | $t->suspend() | |   | |    | | 
| |    | |   | |    | | 
| +---------------+ |   | +---------------+ | 
|      |   |      | 
| Created thread  |   |      | 
| +---------------+ |   |      | 
| |    | |   |      | 
| | capture()  | |   |      | 
| |    | |   |      | 
| +---------------+ |   |      | 
|      |   |      | 
+---------------------+   +---------------------+ 

你要求你创建线程未暂停,但你几乎没有确定自己是否被暂停与否的方式。毕竟,capture不会打印任何内容或更改任何外部变量。事实上,你没有理由相信它没有被暂停。

现在,您可能希望启动的程序冻结,但您没有做任何事情来暂停它或其主线程。因此,它将继续运行[1]

如果你想挂起一个外部进程,你可以发送SIGSTOP给它(和SIGCONT来恢复它)。为此,您需要该流程的PID。我建议用IPC::Runpump循环代替capture


  1. 那么,当它试图写入stdout,因为管得满,因为你实际上没有暂停运行capture线程最终会阻塞。
+0

我看了一下'IPC :: Run'文档,但我仍然困惑于如何用'pump'替换'capture'。我尝试从'IPC :: Open2'中用'open2'替换'capture',替换不起作用 –

+0

如何用'run'替换'capture'应该是显而易见的,文档显示'run'是如何运行的只是一个'开始'+'泵'+'完成'。 '$ h-> signal'可以用来发送信号。 – ikegami

+0

用'run'代替'capture'很明显,但用'start + pump + finish'序列替换'run'并不是 –