2011-08-30 91 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... 
相关问题