线程死亡时子进程死亡

时间:2017-09-13 11:05:53

标签: python python-3.x subprocess python-multithreading

我有一个程序可以触发Python计时器来生成子进程。一旦我的程序被终止或终止,这些子进程应该终止。为了做到这一点,我使用" prctl hack",设置一个孩子一旦其父亲去世就应该收到的信号。我得到的不良行为是:即使我的主进程正在运行,孩子们也会被杀死。以下代码重新创建了问题:

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)

您可以注意到,在线程死亡之前,sleep进程仍在运行。在计时器线程死后,它的相应子进程也会死掉,即使主线程处于活动状态。

1 个答案:

答案 0 :(得分: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线程死亡后仍然存在,但是当主线程退出时仍会终止。