栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python:当父异常终止时,如何杀死子进程?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python:当父异常终止时,如何杀死子进程?

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

在Linux上,

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

在Windows上,最可靠的选择是使用Job对象。想法是创建一个“作业”(一种用于流程的容器),然后将子流程放入作业中,并设置魔术选项,指出“当没有人握住该作业的“手柄”时,然后杀死其中的进程”。默认情况下,作业的唯一“句柄”是父进程持有的句柄,并且当父进程死掉时,操作系统将遍历并关闭其所有句柄,然后注意这意味着没有用于工作。因此,它会按要求杀死孩子。包含使用该

win32api
模块执行此操作的示例代码。该代码使用
CreateProcess
发射子,而不是
subprocess.Popen
。原因是他们需要为生成的子项获取一个“进程句柄”,并
CreateProcess
默认将其返回。如果您愿意使用
subprocess.Popen
,那么这是该答案中代码的(未经测试的)副本,它使用
subprocess.Popen
OpenProcess
代替
CreateProcess

import subprocessimport win32apiimport win32conimport win32jobhJob = win32job.CreateJobObject(None, "")extended_info = win32job.QueryInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation)extended_info['BasicLimitInformation']['LimitFlags'] = win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEwin32job.SetInformationJobObject(hJob, win32job.JobObjectExtendedLimitInformation, extended_info)child = subprocess.Popen(...)# Convert process id to process handle:perms = win32con.PROCESS_TERMINATE | win32con.PROCESS_SET_QUOTAhProcess = win32api.OpenProcess(perms, False, child.pid)win32job.AssignProcessToJobObject(hJob, hProcess)

从技术上讲,这里有一个很小的比赛条件,以防孩子在

Popen
OpenProcess
呼叫之间死亡,您可以决定是否要担心这一点。

使用作业对象的一个​​缺点是,在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, WinErrorfrom ctypes.wintypes import DWORD, BOOL, HANDLE# Magic value from http://msdn.microsoft.com/en-us/library/ms684880.aspxSYNCHRonIZE = 0x00100000kernel32 = WinDLL("kernel32.dll")kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)kernel32.OpenProcess.restype = HANDLEparent_handle = kernel32.OpenProcess(SYNCHRONIZE, False, parent_pid)# Block until parent exitsos.waitpid(parent_handle, 0)os._exit(0)

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

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

希望有帮助!



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/367563.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号