2011-06-29 5 views
3

私はこの問題のための質問を開き、問題を解決するのに十分な答えを得られませんでした(私の問題を説明する厳しさが欠けている可能性が高い):Zombie process in python multiprocessing daemonデーモンプロセス内のPythonマルチプロセッシングプール

Popenを使用してコマンドを実行するためにワーカーのプールを使用するPythonデーモンを実装しようとしています。私はhttp://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

から基本的なデーモンを借りてきた私はinitdaemonize(または均等start)とstop方法を変更しました。私はprint文を使用してコードをデバッグできるように、私は標準入力、stdoutとstderrを設定しておりません

def __init__(self, pidfile): 
#, stdin='/dev/null', stdout='STDOUT', stderr='STDOUT'): 
    #self.stdin = stdin 
    #self.stdout = stdout 
    #self.stderr = stderr 
    self.pidfile = pidfile 
    self.pool = Pool(processes=4) 

:ここinit方法への変更があります。また、私はいくつかの場所にこのプールを移動しようとしましたが、これは例外を生成しない唯一の場所です。ここで

daemonize方法に変更されています。私はデバッグできるよう

def daemonize(self): 
    ... 

    # redirect standard file descriptors 
    #sys.stdout.flush() 
    #sys.stderr.flush() 
    #si = open(self.stdin, 'r') 
    #so = open(self.stdout, 'a+') 
    #se = open(self.stderr, 'a+', 0) 
    #os.dup2(si.fileno(), sys.stdin.fileno()) 
    #os.dup2(so.fileno(), sys.stdout.fileno()) 
    #os.dup2(se.fileno(), sys.stderr.fileno()) 

    print self.pool 

    ... 

同じことが、私はIOをリダイレクトしていません。ここのプリントは、私がプールの場所を確認できるように使用されています。

そして stop方法の変更:

def stop(self): 
    ... 

    # Try killing the daemon process 
    try: 
     print self.pool 
     print "closing pool" 
     self.pool.close() 
     print "joining pool" 
     self.pool.join() 
     print "set pool to None" 
     self.pool = None 
     while 1: 
      print "kill process" 
      os.kill(pid, SIGTERM) 

    ... 
ここ

アイデアは、私が唯一のプロセスを殺すだけでなく、プールをクリーンアップする必要はないということです。 self.pool = Noneは、動作しなかった問題を解決するための単なるランダムな試みです。最初は、これは、self.pool.close()self.pool.join()がwhileループの内側にあるos.kill(pid, SIGTERM)のときに発生していたゾンビの子供の問題だと思っていました。これは、プールの場所をprint self.poolで調べることを決定する前です。これを実行した後、デーモンの起動時と停止時にプールが同じではないと私は考えます。ここではいくつかの出力は次のとおりです。

[email protected]:~/pyCode/jobQueue$ sudo ./jobQueue.py start 
<multiprocessing.pool.Pool object at 0x1c543d0> 
[email protected]:~/pyCode/jobQueue$ sudo ./jobQueue.py stop 
<multiprocessing.pool.Pool object at 0x1fb7450> 
closing pool 
joining pool 
set pool to None 
kill process 
kill process 
... [ stuck in infinite loop] 

オブジェクトの異なる場所は、彼らが同じプールではなく、それらの1つは、おそらくゾンビであることを私に示唆しますか?

CTRL+Cした後、ここで私はps aux|grep jobQueueから得るものです:私は別の場所の数にself.pool = Pool(processes=4)を移動しようとしている

root  21161 0.0 0.0 50384 5220 ?  Ss 22:59 0:00 /usr/bin/python ./jobQueue.py start 
root  21162 0.0 0.0  0  0 ?  Z 22:59 0:00 [jobQueue.py] <defunct> 
me  21320 0.0 0.0 7624 940 pts/0 S+ 23:00 0:00 grep --color=auto jobQueue 

start()' orに移動した場合、daemonize()methods,が表示されます。print self.pool`はNoneTypeであるという例外をスローします。また、場所はポップアップするゾンビプロセスの数を変更するようだ。

現在、私はワーカーを介して何かを実行する機能を追加していません。私の問題は、労働者のプールを正しく設定することと完全に関連しているようです。この問題を解決するためのあらゆる情報や、Popenを使用して一連のコマンドを実行するためのワーカーのプールを使用するデーモンサービスの作成についてのアドバイスに感謝します。私はそれほど遠からず、私は先に直面している挑戦を知らない。私はちょうど私自身のプールを書く必要があるかもしれないと思っていますが、ここでプールを働かせる素晴らしいトリックがあれば、それは素晴らしいでしょう。

+0

私は何をする必要があるのか​​分かっていると思いますが、どうやってやるのか分かりません。デーモンの内部では、pidファイルに書き込みます。 startまたはstopが呼び出されるたびに、デーモンのPIDがファイルから取得されます。私はプールプロセスのPIDで同じことをする必要がありますが、どのように? –

答えて

1

解決策はdaemonizeメソッドの最後の行にself.pool = Pool(process=4)を入れることです。さもなければ、プールはどこかで失われてしまいます(おそらくforkである)。その後、プールはrunメソッド内でアクセスすることができます。このメソッドは、デーモン化するアプリケーションによってオーバーロードされます。ただし、stopメソッドでプールにアクセスすることはできません。そうしないと、NoneType例外が発生します。私はより洗練されたソリューションがあると信じていますが、これはうまくいきます。プールがまだ動作しているときにstopを失敗させたい場合は、runと何らかの形式のメッセージに追加機能を追加する必要がありますが、現在はこれに関心がありません。

+0

実際には非常に簡単でした。私がする必要があったのは、 'self'pool = Pool(process = 4)'をデーモンの 'run'メソッドに入れていましたが、' close' 'join 'プールをうまくクリーンアップする方法。他の解決策は高く評価されます。 –

関連する問題