簡體   English   中英

如果父進程在 Python 中被殺死,則殺死子進程

[英]Kill Child Process if Parent is killed in Python

我正在從 python 腳本生成 5 個不同的進程,如下所示:

p = multiprocessing.Process(target=some_method,args=(arg,))
p.start()

我的問題是,當父進程(主腳本)以某種方式被殺死時,子進程繼續運行。

當父進程被殺死時,有沒有辦法殺死像這樣產生的子進程?

編輯:我正在嘗試這個:

p = multiprocessing.Process(target=client.start,args=(self.query_interval,))
p.start()
atexit.register(p.terminate)

但這似乎不起作用

我自己也遇到過同樣的問題,我有以下解決方案:

在調用p.start()之前,您可以設置p.daemon=True 然后正如這里提到的python.org 多處理

當一個進程退出時,它會嘗試終止其所有守護進程。

孩子不會收到父母死亡的通知,它只會以另一種方式工作。

但是,當一個進程終止時,它的所有文件描述符都將關閉。 如果管道的另一端選擇了要讀取的管道,則會通知管道的另一端。

因此,您的父母可以在生成進程之前創建一個管道(或者實際上,您可以將 stdin 設置為管道),而孩子可以選擇它進行閱讀。 當父端關閉時,它將報告准備好閱讀。 這需要您的孩子運行主循環,或者至少定期調用選擇。 如果你不想那樣做,你需要一些管理器進程來做,但是當那個進程被殺死時,事情又會崩潰。

如果您有權訪問父 pid,則可以使用這樣的方法

import os
import sys
import psutil


def kill_child_proc(ppid):
    for process in psutil.process_iter():
        _ppid = process.ppid()
        if _ppid == ppid:
            _pid = process.pid
            if sys.platform == 'win32':
                process.terminate()
            else:
                os.system('kill -9 {0}'.format(_pid))

kill_child_proc(<parent_pid>)

我的情況是使用Queue對象與子進程通信。 無論出於何種原因,已接受答案中建議的daemon標志不起作用。 這是一個最小的例子,說明在這種情況下如何讓孩子們優雅地死去。

主要思想是每隔一秒左右暫停子工作執行並檢查父進程是否還活着。 如果它不存在,我們關閉隊列並退出。

請注意,如果使用SIGKILL殺死主進程,這也有效

import ctypes, sys
import multiprocessing as mp

worker_queue = mp.Queue(maxsize=10)

# flag to communicate the parent's death to all children
alive = mp.Value(ctypes.c_bool, lock=False)
alive.value = True

def worker():
    while True:
        # fake work
        data = 99.99
        # submit finished work to parent, while checking if parent has died
        queued = False
        while not queued:
            # note here we do not block indefinitely, so we can check if parent died
            try:
                worker_queue.put(data, block=True, timeout=1.0)
                queued = True
            except: pass
            # check if parent process is alive still
            par_alive = mp.parent_process().is_alive()
            if not (par_alive and alive.value):
                # for some reason par_alive is only False for one of the children;
                # notify the others that the parent has died
                alive.value = False
                # appears we need to close the queue before sys.exit will work
                worker_queue.close()
                # for more dramatic shutdown, could try killing child process;
                # wp.current_process().kill() does not work, though you could try
                # calling os.kill directly with the child PID
                sys.exit(1)

# launch worker processes
for i in range(4):
    child = mp.Process(target=worker)
    child.start()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM