6

Pythonデーモンを調査した後、このウォークスルーが最も堅牢であると思われました: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

今、動作していると思われるデーモン クラス内にワーカーのプールを実装しようとしています (コードを完全にテストしていません) が、終了時にゾンビ プロセスが発生します。子供からのリターンコードを待つ必要があることを読みましたが、これを行う必要がある方法がまだ正確にわかりません。

以下にいくつかのコード スニペットを示します。

def stop(self):
    ...
    try:
        while 1:
            self.pool.close()
            self.pool.join()
            os.kill(pid, SIGTERM)
            time.sleep(0.1)
    ...

os.killpgここで、いくつかの方法を試しos.waitましたが、改善されませんでした。closing私は/joiningの前後にプールで遊んだこともありますos.kill。このループはそのままでは終わらず、ヒットするとすぐにos.killゾンビプロセスが発生します。デーモンself.pool = Pool(processes=4)のセクションで発生します。__init__run(self)後に実行される からstart(self)、 を呼び出しますself.pool.apply_async(self.runCmd, [cmd, 10], callback=self.logOutput)。ただし、それを調べる前に、このゾンビ プロセスに対処したいと思いました。

このゾンビプロセスを回避するために、デーモン内にプールを適切に実装するにはどうすればよいですか?

4

1 に答える 1

4

子/デーモン プロセスで何が起こっているかを知らずに、答えに 100% の自信を持つことはできませんが、これが可能かどうかを検討してください。子プロセスにワーカー スレッドがあるため、実際には、SIGTERM を受け取ったら、これらのスレッドすべてに参加するロジックを組み込む必要があります。そうしないと、プロセスが終了しない場合があります (終了したとしても、正常に終了しない場合があります)。これを行うには、次のことが必要です。

  • SIGTERM シグナルをキャプチャし、メイン スレッドのイベントをトリガーする子/デーモン プロセスで使用されるシグナル ハンドラを作成します。
  • 子/デーモン プロセスのメイン スレッド (非常に重要) にシグナル ハンドラをインストールします。
  • SIGTERM のイベント ハンドラは、子/デーモン プロセスのすべてのスレッドに停止命令を発行する必要があります。
  • すべてのスレッドは、完了時に join() する必要があります (SIGTERM が自動的にすべてを破棄すると想定している場合は、このロジックも実装する必要があるかもしれません)。
  • すべてが結合されてクリーンアップされたら、メインスレッドを終了できます

I/O やあらゆる種類のスレッドがある場合、これは非常に面倒な作業になります。

また、シグナル ハンドラーを使用している場合、イベント リスナーの特定の戦略が重要であることを実験で確認しました。たとえば、select.select() を使用する場合、タイムアウトを使用し、タイムアウトが発生した場合は再試行する必要があります。そうしないと、シグナル ハンドラーが実行されません。イベント用の Queue.Queue オブジェクトがあり、イベント リスナーがその .get() メソッドを呼び出す場合は、タイムアウトを使用する必要があります。そうしないと、シグナル ハンドラーが実行されません。(VM 内で C で実装された「実際の」シグナル ハンドラーは実行されますが、タイムアウトを使用しない限り、Python シグナル ハンドラーは実行されません。)

幸運を!

于 2011-06-21T20:26:03.643 に答える