2016-07-22 110 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'並不是 –