python 杀死子进程_Python:当父代死亡时如何杀死子进程?

呃,我昨天刚刚研究一下这个!假设你不能改变子程序:

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

在Windows上,最可靠的选择是使用Job object.这个想法是您创建一个“作业”(一种用于进程的容器),然后将子进程放入作业,并设置说明的魔术选项“当没有人持有该作业的”句柄“,然后杀死它中的进程”.默认情况下,作业的唯一“句柄”是您的父进程所持有的“handle”,当父进程中断时,操作系统将通过并关闭其所有句柄,然后注意,这意味着没有打开的句柄工作.因此,根据要求,它会杀死小孩. (如果您有多个子进程,则可以将它们全部分配给相同的作业.)This answer具有使用win32api模块执行此操作的示例代码.该代码使用CreateProcess来启动子代码,而不是subprocess.Popen.原因是它们需要为生成的子进程获取“进程句柄”,并且CreateProcess默认返回.如果你宁愿使用subprocess.Popen,那么这里是一个(未经测试的)该答案的代码副本,它使用subprocess.Popen和OpenProcess而不是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)

在技​​术上,这里有一个很小的竞争条件,如果孩子在Popen和OpenProcess调用之间死亡,你可以决定是否要担心.

使用作业对象的一个​​缺点是,当在Vista或Win7上运行时,如果您的程序从Windows shell启动(即通过单击图标),那么可能会出现already be a job object assigned并尝试创建新的作业对象将失败. Win8修复这个(通过允许作业对象嵌套),或者如果你的程序是从命令行运行的话,那应该是正常的.

如果你可以修改孩子(例如,像使用多重处理一样),那么可能最好的选择是以某种方式将父代的PID传递给孩子(例如,作为命令行参数,或者在args =参数中进行multiprocessing.Process)接着:

在POSIX上:在孩子中产生一个只会偶尔调用os.getppid()的线程,如果返回值停止匹配从父进程传入的pid,则调用os._exit(). (这种方法可以移植到所有Unix,包括OS X,而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)

这样可以避免我提到的任务对象可能出现的问题.

如果你想要真的,真的确定,那么你可以结合所有这些解决方案.

希望有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值