您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python:当父母去世时,如何杀死子进程?

Python:当父母去世时,如何杀死子进程?

呵呵,昨天我只是在自己研究!假设您无法更改子程序:

在Linux上,prctl(PR_SET_PDEATHSIG, ...)可能是唯一可靠的选择。(如果绝对有必要终止子进程,那么您可能希望将死亡信号设置为SIGKILL而不是SIGTERM;链接到的代码使用SIGTERM,但是子级确实可以选择忽略SIGTERM。 )

在Windows上,最可靠的选择是使用Job对象。这个想法是,您创建一个“ Job”(一种用于流程的容器),然后将子流程放入Job中,并设置了一个神奇的选项,说“当没有人握住该Job的“手柄”时,然后杀死其中的进程”。认情况下,作业的唯一“句柄”是父进程持有的句柄,并且当父进程死亡时,操作系统将遍历并关闭其所有句柄,然后注意这意味着没有用于工作。因此,它会按要求杀死孩子。(如果您有多个子进程,则可以将它们全部分配给同一作业。)此答案包含使用win32api模块执行此操作的示例代码。该代码使用CreateProcess发射孩子,而不是subprocess.Popen。原因是他们需要为生成的子项获取一个“进程句柄”,并CreateProcess认将其返回。如果您愿意使用subprocess.Popen,那么这是该答案中代码的(未经测试的)副本,它使用subprocess.PopenOpenProcess代替CreateProcess

import subprocess
import win32api
import win32con
import win32job

hJob = win32job.CreateJobObject(None, "")
extended_info = win32job.QueryInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation)
extended_info['BasicLimitInformation']['LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
win32job.SetInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation, extended_info)

child = subprocess.Popen(...)
# Convert process id to process handle:
perms = win32con.PROCESS_TERMINATE | win32con.PROCESS_SET_QUOTA
hProcess = win32api.OpenProcess(perms, False, child.pid)

win32job.AssignProcessToJobObject(hJob, hProcess)

从技术上讲,这里有一个很小的比赛条件,以防孩子在PopenOpenProcess通话之间死亡,您可以决定是否要担心这一点。

使用作业对象的一个??缺点是,在Vista或Win7上运行时,如果您的程序是从Windows Shell启动的(即,通过单击图标),则可能已经有一个作业对象被分配并试图创建一个作业对象。新作业对象将失败。Win8可以解决此问题(通过允许嵌套作业对象),或者如果您的程序是从命令行运行的,那么应该可以。

如果您 可以 修改子级(例如,如使用时multiprocessing),那么最好的选择可能是以某种方式将父级的PID传递给子级(例如,作为命令行参数或到的args=参数multiprocessing.Process),然后:

在POSIX上:在子级中生成一个os.getppid()偶尔会调用的线程,如果返回值停止匹配从父级传入的pid,则调用os._exit()。(这种方法可移植到包括OS X在内的所有Unix上,而prctl诀窍是特定于Linux的。)

在Windows上:在使用OpenProcess和的子代中产生一个线程os.waitpid。使用ctypes的示例:

from ctypes import WinDLL, WinError
from ctypes.wintypes import DWORD, BOOL, HANDLE
# Magic value from http://msdn.microsoft.com/en-us/library/ms684880.aspx
SYNCHRONIZE = 0x00100000
kernel32 = WinDLL("kernel32.dll")
kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
kernel32.OpenProcess.restype = HANDLE
parent_handle = kernel32.OpenProcess(SYNCHRONIZE, False, parent_pid)
# Block until parent exits
os.waitpid(parent_handle, 0)
os._exit(0)

这避免了我提到的作业对象的任何可能的问题。

如果您想真正确定,那么可以组合所有这些解决方案。

希望有帮助!

python 2022/1/1 18:28:33 有453人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶