4

waitpid とタイムアウトに関する多くの質問があることは承知していますが、それらはすべて、アラーム ハンドラ内から子を殺すことでこれをカバーしています。

それは私が望むものではありません。プロセスを実行し続けたいのですが、waitpid からディスパッチします。

私が解決しようとしている根底にある問題は、キューを処理するメイン ループを持つデーモン プロセスです。タスクは一度に 1 つずつ処理されます。

タスクがハングすると、メイン ループ全体がハングします。これを回避することは、当然の選択のようfork()に思えました。waitpidそれでもタスクがハングすると、ループがハングします。

waitpid をまったく使用しない回避策を考えることができますが、ハングする可能性のあるタスクと並行して一度に 1 つのタスクを処理したいので、実行中のプロセスを別の方法で追跡する必要があります。

タスクを強制終了することもできますが、正確に何が問題なのかを調べるために実行したいと思います。一部のデバッグ情報をダンプする 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";
}
4

3 に答える 3

7

タスクがハングすると、メイン ループ全体がハングします。この fork() と waitpid を回避することは、当然の選択のように思えました。それでもタスクがハングすると、ループがハングします。

オプションwaitpidでご利用ください。このようにして、親プロセスを中断することはなく、子がまだ終了していないときにWNOHANGすぐに戻ります。0メイン ループでは、すべての子 (タスク) を定期的にポーリングする必要があります。

于 2011-08-30T11:51:51.047 に答える
5

すべての子を定期的にポーリングする代わりに、シグナルハンドラを設定して SIGCHLD を処理することをお勧めします... perlipc から:

 use POSIX ":sys_wait_h";
    $SIG{CHLD} = sub {
        while ((my $child = waitpid(-1, WNOHANG)) > 0) {
            $Kid_Status{$child} = $?;
        }
    };
    # do something that forks...
于 2013-10-16T20:39:00.920 に答える
1

SIGCHLD を有効にして処理することも可能です。ポーリングせずに子プロセスの状態の変化を通知します。マニュアル ページの sigprocmask(2) と signal(3) を参照してください。

于 2013-01-25T22:04:17.640 に答える