2017-10-15 6 views
1

トレイアイコンを実装しようとしているので、プロセス(jackd)を制御できます。最も顕著なのforkした子プロセスとそのjackdサブプロセスをPythonでkillする方法

  • 私は
  • ログ記録の目的のためにプロセスのstdoutとstderrを読みたい、私は殺害を引き起こしているメインプログラムのメニューエントリ

からプロセスを殺すことができるようにしたいです私の頭痛。私はstdoutとstderrを読むと、アイコンを反応させ続けるために余分なスレッド/プロセスでこれを行わなければならないと信じています。そこでfork()を使用して子プロセスを作成し、子にsetsid()を呼び出しました。その子プロセスは、その後

from subprocess import PIPE, STDOUT, Popen 
def runAndLog(self, cmd): 
    po = Popen(cmd, stdout=PIPE, stderr=STDOUT) 
    line = po.stdout.readline() 
    while line: 
     print(line.rstrip()) 
     line = po.stdout.readline() 
self.runAndLog(["jackd","-R", "-P80", "-t5000", "-dfirewire", "-r44100", "-p256", "-n3"]) 

今、私は私が私のフォークの子プロセスを取得し、同じプロセスグループにjackdができることを期待していたので、私は一度ではなく、私の驚きに、両方殺すことができるsubprocessモジュールを使用してjackd呼び出しますPopenは、新しいプロセスグループと新しいセッションを作成しました:

PID PPID PGID SID COMMAND 
5790 5788 5788 31258 python (parent, main) 
5791 5790 5791 5791 python (forked child after setsid - ok) 
5804 5791 5804 5804 jackd (grandchild created by Popen) 

ので、子供が孫を殺さないと私は孫のPID(5804)を作るのいずれかのきれいな方法が表示されていない殺害でmainに知られています明示的にそれを殺すために。私はおそらく、瀕死の子供が孫を殺させるために、信号をトリッキーに使うことができるかもしれませんが、私はこれをすることをためらっています。

また、SIDが私の子供のSIDと異なるので、jackdプロセスでそれを子供のプロセスグループに強制的に使用することはできません。setpgid

私はどちらか

  • は、新しいセッションを作成しないようにpopenのを説得する必要がある、または
  • subprocess未満魔法でモジュールを使用していますが、まだstdoutとstderrを読むために私をalowsいる。信じる

しかし、私はどちらかの方法を知りません。確かにプロセスグループに関する私の知識は幾分限られています。

/home/martin >python --version 
Python 2.7.1 

更新10月12日

私は、新しいセッションがパイソンではなくjackd自体によって作成されていないことがわかりました。 jackdをxtermに置き換えると、すべて正常です。

PID PPID PGID SID COMMAND 
12239 4024 12239 4024 python (parent, main) 
12244 12239 12244 12244 python (forked child after setsid - ok) 
12249 12244 12244 12244 xterm (grandchild has same PGID and SID - ok) 

は、私はまた、this

これらのジャック日数呼び出したがsetsid()自体は唯一

にオプションを残し、新たな プロセスグループリーダー

として設立取得するために

  • メイクジャックのPIDをに知らせる210とjackd

その上の任意のアドバイス殺す殺す明示的にそれを殺す、または

  • は、瀕死の子供を持っていますか?

  • +0

    この回答は役に立ちますか? http://stackoverflow.com/a/4791612 –

    +0

    これは私がやっていることとほぼ同じです。しかし、私は問題が実際にはpythonではなくjackdであることを発見しました。私はそれに応じて私の質問を更新します。 –

    +0

    スレッドだけを使って、 'jack'を直接制御してみませんか?実際のコマンドを制御するために、なぜ独立した子プロセスを作るのですか?それをずっと複雑にすることのメリットは何ですか? –

    答えて

    1

    あなたの孫が独自のセッションとsidを設定しているので、group-killが正しく動作することは期待できません。次の3つのオプションがあります。子供プロセスのツリー全体にわたる

    1. 反復し、そして(彼らは子供たちを再起動しないように)親から始まるそれらすべてを殺します。醜い複雑すぎる解決策。

    2. メイン(ルート)プロセスのスレッドを使用して、jackの子を直接制御します。メリットがないため、中間の子プロセスはおそらくここでは必要ありません。これは可能な最も簡単な解決策です。

    3. あなたはまだ中間子プロセスを持っている必要があります場合は、唯一の方法は、子供に送られる終了シグナルをキャッチし、孫にそれらを送信することである。

    child.py

    import signal 
    import subprocess 
    
    # The signal handler for the child process, which passes it further to the grandchild. 
    def handler(signum, frame): 
        print('Killing self, killing the children') 
    
        os.kill(proc.pid, signal.SIGTERM) 
    
        # wait for the process to die gracefully for N secs. 
        time.sleep(5) 
    
        os.kill(proc.pid, signal.SIGKILL) 
    
    cmd = ["jackd","-R", "-P80", "-t5000", "-dfirewire", "-r44100", "-p256", "-n3"] 
    po = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
    
    signal.signal(signal.SIGTERM, handler) 
    
    for line in po.stdout: 
        print(line.rstrip()) 
    

    シグナルハンドラは、プロセス通信が開始される前にインストールされています(行の読み取り)。

    ルートプロセスが子プロセスを "正常に"(たとえばSIGTERMを使用して)強制終了すると、シグナルは孫に渡され、終了/強制終了されます。あなたは殺して待って強制殺すという論理を拡張することさえできます。

    ただし、子プロセスがSIGKILLで強制終了された場合、このシグナルをキャッチする可能性はなく、孫は孤立したままになります。 SIGKILLは設計上捕まえることができないからです。

    関連する問題