2016-03-24 9 views
5

答えは私の目の前にあるかもしれませんが、私はまだ分かりません。誰かがこれを私に説明した後、ダーウィンは私に電話をかけてくれると確信しています。デーモンプログラムがjoin()を使わずに終了しないのはなぜですか?

例はat this link hereですが、私は実験をして理解を助けるためにいくつかの変更を加えましたが、ここで

はコードです:

import multiprocessing 
import time 
import sys 

def daemon(): 
    p = multiprocessing.current_process() 
    print 'Starting: ', p.name, p.pid 
    sys.stdout.flush() 
    time.sleep(2) 
    print 'Exiting: ', p.name, p.pid 
    sys.stdout.flush() 

def non_daemon(): 
    p = multiprocessing.current_process() 
    print 'Starting: ', p.name, p.pid 
    sys.stdout.flush() 
    time.sleep(6) 
    print 'Exiting: ', p.name, p.pid 
    sys.stdout.flush() 

if __name__ == '__main__': 
    d = multiprocessing.Process(name='daemon', target=daemon) 
    d.daemon = True 

    n = multiprocessing.Process(name='non-daemon', target=non_daemon) 
    n.daemon = False 

    d.start() 
    time.sleep(1) 
    n.start() 
# d.join() 

とコードの出力は次のとおりです。最後に()の参加がコメント解除された場合

Starting: daemon 6173 
Starting: non-daemon 6174 
Exiting: non-daemon 6174 

、出力は次のとおりです。

Starting: daemon 6247 
Starting: non-daemon 6248 
Exiting: daemon 6247 
Exiting: non-daemon 6248 

デーモンのスリープが2秒であるのに対し、デーモン以外のデーモンは6秒ですが、私は混乱しています。最初のケースで「終了」メッセージが表示されないのはなぜですか?デーモンは非デーモンの前に目を覚まし、メッセージを表示する必要があります。

サイトからの説明のようなある:

出力(メイン プログラムを含む)は、非デーモンプロセスの全てので、デーモン プロセスから「終了」メッセージが含まれていませんデーモンプロセスが2秒後にスリープ状態になる前に終了する。 スリープ。

しかし、非デーモンの前にデーモンが起動するように変更しました。私はここで何が欠けていますか?あなたの助けを前にありがとう。

編集:私のpython 2.7を使用しています言及し忘れたが、どうやらこの問題は、これが追跡するのも楽しいものだったのPython 3.xの

答えて

4

でもあります。これらのドキュメントは、デーモン以外のプロセスをすべて同等のものとして記述する点で、やや誤解を招きます。デーモン以外のプロセスが存在するということは、プロセス "family"が生きていることを意味します。 But that's not how it's implemented.親プロセスは他のプロセスよりも「同等」です。メインプロセスは最初terminateのすべてdaemonの子プロセス、その後、joinのすべての子プロセスが非daemon子プロセスが終了するのを待つために、それを終了したときに

for p in active_children(): 
    if p.daemon: 
     info('calling terminate() for daemon %s', p.name) 
     p._popen.terminate() 

for p in active_children(): 
    info('calling join() for process %s', p.name) 
    p.join() 

multiprocessingは以下のんatexitハンドラを登録します子供たちdaemonのリソースをクリーンアップします。

それは、この順序であなたの非daemonProcessstart秒後の瞬間をクリーンアップを実行しているので、メインプロセスは、クリーンアップと強制的にterminatedaemonProcessを開始します。(完全daemonの全体のポイントを敗北)daemonプロセスをINGのちょうどjoin、これは手動で非daemonプロセスをINGのjoinように単純であってもよいしない定着こと

注意。 atexitハンドラが呼び出されることを防ぎ、terminateの子サブキットをクリーンアップします。

これはおそらくバグです(3.5.1まで存在するようですが、私は自分自身を再現しました)が、それが動作のバグかドキュメントのバグかは議論の余地があります。

+2

これはバグであると判断しました。(スレッドの代わりにプロセスを使って 'マルチプロセッシング'がエミュレートされると思われる) 'threading'とは異なり、デーモンスレッドは動作し続けます。もしくはそうでないか)。 [bug#26633](https://bugs.python.org/issue26633)を開きました。 – ShadowRanger

+0

この問題を調査する上で、そしてそれを上回ることのために。私が狂っていないとダーウィンは私のために呼び出すことはありません聞いてうれしい、少なくとも今回は=) – Classified

関連する問題