2017-09-13 12 views
3

私はサブプロセスを生成するためにPythonタイマーを起動するプログラムを持っています。これらのサブプロセスは、私のプログラムが終了したり、終了したりすると終了する必要があります。これを行うために、私は "prctl hack"を使用しています。私が得意でない行動は、私の主なプロセスが実行中であっても、子供たちが殺されることです。あなたがスレッドが死ぬ前に、sleepプロセスがまだ実行されている、それに気づくことができスレッドが死ぬとサブプロセスが死ぬ

from threading import Timer 
import time 
import os 
import subprocess 
import ctypes 
import signal 

def set_pdeathsig(): 
     print("child PID: %d" % os.getpid()) 
     print("child's parent PID: %d" % os.getppid()) 
     prctl = ctypes.CDLL("libc.so.6").prctl 
     PR_SET_PDEATHSIG = 1 
     prctl(PR_SET_PDEATHSIG, signal.SIGTERM) 

def thread1(): 
     subprocess.Popen(['sleep', 'infinity'], preexec_fn=set_pdeathsig) 
     time.sleep(10) 
     print("thread 1 finished") 

def thread2(): 
     subprocess.Popen(['sleep', 'infinity'], preexec_fn=set_pdeathsig) 
     time.sleep(10) 
     print("thread 2 finished") 

print("main thread PID: %d" % os.getpid()) 

t1 = Timer(1, thread1) 
t2 = Timer(1, thread2) 

t1.start() 
t2.start() 

time.sleep(100) 

:次のコードは、問題を再作成します。タイマースレッドが終了すると、メインスレッドが稼働していても、それぞれのサブプロセスが終了します。

+0

明らかに、あなたは関数 'os.setpgid'を呼び出しません。 –

+0

ありがとう@TheophileDano、これは以前のテストのコードです。それはそこにはないはずです。私がそれを取り除くと、問題は依然として続きます。 –

答えて

1

これは予想され、文書化された動作です。 prctl(2)のマニュアルページから:

 Warning: the "parent" in this case is considered to be the 
     thread that created this process. In other words, the signal 
     will be sent when that thread terminates (via, for example, 
     pthread_exit(3)), rather than after all of the threads in the 
     parent process terminate. 

これは、サブプロセスを別の場所に作成する必要があることを意味します。終了したスレッドでそれを行うと、サブプロセスが期待どおりに終了し、その周りに方法がありません。

私は別のスレッドを追加し、そこから起動を処理します。この作業のようなものがありますか:

from threading import Timer 
from threading import Thread 
import queue 
import time 
import os 
import subprocess 
import ctypes 
import signal 

def set_pdeathsig(): 
    print("child PID: %d" % os.getpid()) 
    print("child's parent PID: %d" % os.getppid()) 
    prctl = ctypes.CDLL("libc.so.6").prctl 
    PR_SET_PDEATHSIG = 1 
    prctl(PR_SET_PDEATHSIG, signal.SIGTERM) 

def thread1(q): 
    q.put(["sleep", "infinity"]) 
    time.sleep(5) 
    print("thread 1 finished") 

def thread2(q): 
    q.put(["sleep", "infinity"]) 
    time.sleep(5) 
    print("thread 2 finished") 

def process_manager(q): 
    while True: 
     foo = q.get() 
     subprocess.Popen(foo, preexec_fn=set_pdeathsig) 

print("main thread PID: %d" % os.getpid()) 

qu = queue.Queue() 
pm_thread = Thread(group=None, target=process_manager, args=(qu,)) 
pm_thread.daemon = True 
pm_thread.start() 


t1 = Timer(1, thread1, args=(qu,)) 
t2 = Timer(1, thread2, args=(qu,)) 

t1.start() 
t2.start() 

time.sleep(15) 

これはあなたがしたいことです(Python3.5はテストに使用しました)。もちろん、オーケストレーションスレッドが適切でない理由があるかもしれませんが、私はそれをソリューション候補として提供しています。サブプロセスはTimerスレッドが破棄されても残りますが、メインスレッドが終了すると終了します。

関連する問題