2011-08-30 87 views
4

我知道關於waitpid和超時的許多問題,但他們都通過從報警處理程序中殺死孩子來覆蓋這個問題。如何在不殺死孩子的情況下超時waitpid?

這不是我想要的,我想保持進程運行,但從waitpid調度它。

我嘗試解決的下層問題是帶有處理隊列的主循環的守護進程。一次處理一個任務。

如果一個任務掛起整個主循環掛起。繞過這個fork()waitpid似乎是一個明顯的選擇。如果一個任務掛起,循環掛起。

我可以想到的解決方法,我根本不使用waitpid,但我必須以另一種方式跟蹤正在運行的進程,因爲我仍然想要一次處理一個任務,並行執行可能掛起的任務。

我甚至可以殺死任務,但我想運行它來檢查到底發生了什麼問題。轉儲一些調試信息的kill處理程序也是可能的。

無論如何,解決這個問題的最方便的方法是如果可能會超時waitpid。

編輯:

這是我如何使用fork()和waitpid函數,它可能更清楚什麼是孩子的意思。

my $pid = fork(); 

if ($pid == 0){ 
    # i am the child and i dont want to die 
} 
elsif ($pid > 0) { 
    waitpid $pid, 0; 
    # i am the parent and i dont want to wait longer than $timeout 
    # for the child to exit 
} 
else { 
    die "Could not fork()"; 
} 

編輯:

使用waitpid函數WNOHANG我想要做什麼。這種用法很好嗎?或者你會以不同的方式做到這一點?

use strict; 
use warnings; 
use 5.012; 
use POSIX ':sys_wait_h'; 

my $pid = fork(); 

if ($pid == 0){ 
    say "child will sleep"; 
    sleep 20; 
    say "child slept"; 
} 
else { 
    my $time = 10; 
    my $status; 
    do { 
     sleep 1; 
     $status = waitpid -1, WNOHANG; 
     $time--; 
    } while ($time && not $status); 

    say "bye"; 
} 

回答

7

如果任務掛起整個主循環掛起。爲了解決這個問題() 和waitpid似乎是一個明顯的選擇。仍然如果一個任務掛起循環 掛起。

使用waitpidWNOHANG選項。這樣,它不會暫停父進程,並且在孩子尚未退出時立即返回0。在你的主循環中,你必須定期輪詢所有的孩子(任務)。

1

啓用和處理SIGCHLD也是一種可能;它會在不進行輪詢的情況下通知您子進程狀態更改 - 請參見手冊頁中的sigprocmask(2)和signal(3)。

3

代替極化所有的孩子定期,你可能想建立一個信號處理程序來處理SIGCHLD ...從perlipc:

use POSIX ":sys_wait_h"; 
    $SIG{CHLD} = sub { 
     while ((my $child = waitpid(-1, WNOHANG)) > 0) { 
      $Kid_Status{$child} = $?; 
     } 
    }; 
    # do something that forks... 
相關問題