6

File::Tailを実行している 2 つの子プロセスを持つIRC ボット ( Bot::BasicBot ) を実行していますが、終了しても終了しません。したがって、終了する前に、次のようにProc::ProcessTableを使用してそれらを殺しています。

my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
  kill(15, $proc->pid) if ($proc->ppid == $parent);
}

動作しますが、次の警告が表示されます。

14045: !!! 子プロセス PID:14047 が取得されました:
14045: !!! 子プロセス PID:14048 リープ:
14045: !!! プログラムが sig_child() を使用してプロセスをリープしていない可能性があります。
14045: !!! 極端な場合、プログラムがシステムの再起動を強制する可能性があります
14045: !!! このリソースの漏れが修正されない場合。

子プロセスを強制終了するには、他に何ができますか? フォークされたプロセスは、 Bot::BasicBotのforkitメソッドを使用して作成されます。

サンプル スクリプト:

package main;

my $bot = SOMEBOT->new ( server => 'irc.dal.net', channels => ['#anemptychannel'] );

$SIG{'INT'} = 'Handler';
$SIG{'TERM'} = 'Handler';

sub Handler {
$bot->_stop('Leaving.');
}

$bot->run;

package SOMEBOT;

use base qw(Bot::BasicBot);
use File::Tail;
use Proc::ProcessTable;
sub irc_error_state { die if $_[10] =~ /Leaving\./; }
sub help { return; }


sub stop_state {
my $parent=$$;
my $proc_table=Proc::ProcessTable->new();
for my $proc (@{$proc_table->table()}) {
  kill(15, $proc->pid) if ($proc->ppid == $parent);
}
die;

}

sub connected {
my $self = shift;

$self->forkit (
                run     =>  \&announcer,
                body    =>  '/home/somebody/somefile.txt',
                channel =>  '#anemptychannel',
              ) unless $self->{log1};
$self->{log1} = 1;


$self->forkit (
                run     =>  \&announcer,
                body    =>  '/home/somebody/anotherfile.txt',
                channel =>  '#anemptychannel',
              ) unless $self->{log2};
$self->{log2} = 1;

}

sub announcer {
my $announcefile = shift;
my $file=File::Tail->new(name => $announcefile, maxinterval=>5, adjustafter=>7);
while (defined(my $line=$file->read)) { chomp $line; print "$line\n"; }
}
4

4 に答える 4

1

バージョン 0.82 以降、終了時にBot::BasicBot未処理の子プロセス (によって作成されたforkit()) を強制終了します。

于 2011-12-14T13:21:19.630 に答える
1

私はあなたが言及したモジュールのどれにも精通していませんが、過去に Perl プログラムをフォークして書いたときは、通常、この行をメインの親プロセスに入れるだけで十分でした:

$SIG{CHLD} = sub { wait };

そうすれば、子プロセスが終了し、親プロセスが SIGCHLD シグナルを受け取ると、自動的に子を取得しwaitます。

于 2010-03-21T17:43:41.217 に答える
1

古い投稿を掘り起こしていますが、この質問に対する回答を探していたところ、Google 検索でこれがトップの結果になりました。したがって、他の誰かがこれにつまずいた場合に備えて、これが私がやった方法です。

フォークする前に、フォークされたプロセスが通信できるように をセットアップしpipeます。

pipe PARENTRECEIVE,CHILDSEND;

プロセスをフォークし、子から親に新しいプロセス ID をすぐに送信させます。次に、(タイマーまたは SIG のいずれかを介して) 子プロセスがハングしていると思われる場合は、子プロセスを強制終了できます。

my $pid = fork();
if ($pid eq 0) {
  #child block
  my $cid = $$;       
  print CHILDSEND "$cid\n";
  <do child stuff which might hang>
}
else {
  #parent block
  my $child_id = <PARENTRECEIVE>;
  chomp $child_id;
  <do parent stuff>
  <if you think child is hung> {
    kill 1, $child_id;
  }
}

Web サーバーがハングすることがあるので、これを使用して、適切な時間内に HTTP GET 要求にまだ応答しているかどうかを確認します。親のタイマーが切れる前に子が URL の取得を完了しない場合、何かが起きていることを知らせる電子メール アラートを送信します。

于 2013-03-05T15:44:12.030 に答える
0

子プロセスが適切に終了しない理由が気になります。「通常の」状況下では、親は何もする必要はありません (おそらくwaitpid、結果が気になる場合は呼び出すか、処理が完了するまで処理を停止します)。

これはまだあまり答えではありません。おそらく、コードの一部を子に貼り付ける必要があります。しかし、ちょっとしたアドバイスforkです。CPAN モジュールに頼るのではなく、手動で呼び出す単純なプログラムから始めてください。複数のプロセスがシステムによってどのように処理されるかを理解することが重要です。それができたら、いくつかのフレームワークを活用して、多くのプロセスを処理できます。

最近読んでいない場合は、おそらくperldoc perlforkも読んで、いくつかの例を試してみてください。

于 2010-03-21T16:51:39.563 に答える