- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
子进程启动于
subprocess.Popen(arg)
有没有办法确保它在 parent 异常终止时被杀死?我需要它才能在 Windows 和 Linux 上工作。我知道 solution for Linux .
编辑:
如果存在使用不同启动进程方法的解决方案,则可以放宽使用 subprocess.Popen(arg)
启动子进程的要求。
最佳答案
呵呵,我昨天才自己研究这个!假设您不能更改子程序:
在 Linux 上,prctl(PR_SET_PDEATHSIG, ...)
可能是唯一可靠的选择。 (如果绝对有必要杀死子进程,那么您可能希望将死亡信号设置为 SIGKILL 而不是 SIGTERM;您链接到的代码使用 SIGTERM,但如果子进程愿意,可以选择忽略 SIGTERM。 )
在 Windows 上,最可靠的选项是使用 Job object .这个想法是您创建一个“作业”(一种进程容器),然后将子进程放入作业中,并设置“当没有人持有此作业的‘句柄’时,然后杀死其中的进程”。默认情况下,作业的唯一“句柄”是您的父进程持有的,当父进程死亡时,操作系统将检查并关闭其所有句柄,然后注意到这意味着没有打开的句柄工作。因此,它按照要求杀死了 child 。 (如果您有多个子进程,您可以将它们全部分配给同一个作业。)This answer有执行此操作的示例代码,使用 win32api
模块。该代码使用 CreateProcess
来启动子进程,而不是 subprocess.Popen
。原因是他们需要为生成的 child 获取一个“进程句柄”,而 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)
从技术上讲,这里有一个很小的竞争条件,以防 child 在 Popen
和 OpenProcess
调用之间死亡,您可以决定是否要担心这个问题。
使用作业对象的一个缺点是,在 Vista 或 Win7 上运行时,如果您的程序是从 Windows shell 启动的(即,通过单击图标),那么可能会出现 already be a job object assigned并尝试创建新的作业对象将失败。 Win8 解决了这个问题(通过允许嵌套作业对象),或者如果你的程序是从命令行运行的,那么它应该没问题。
如果您可以修改子进程(例如,像使用 multiprocessing
时一样),那么最好的选择可能是以某种方式将父进程的 PID 传递给子进程(例如,作为命令行参数,或在 multiprocessing.Process
的 args=
参数中),然后:
在 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)
这避免了我提到的作业对象的任何可能问题。
如果您想非常非常确定,那么您可以结合所有这些解决方案。
希望有帮助!
关于Python:当父进程死亡时如何杀死子进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23434842/
需要帮助将这些给定的数字打印成星号,但我是编程新手;我该怎么做? #include int main(void) { int a[5]={20,1,5,15,12}; int i=0
使用 Delphi XE 2 我试图确定缩放方向以将缩放效果应用于图像(TImage),但没有找到执行此操作的函数,并且图像的 OnGesture 事件中的 EventInfo 属性没有此信息. 我见
我不知道制服在内存中是如何表示的。 制服似乎会占用宝贵的寄存器空间,但它们最终会传入/通过/传出到全局内存中,对吗? 制服不用时情况会发生变化吗?编译器可以将它们优化掉吗?--在这种情况下,我已经将无
我正在尝试在名为“timeclock”的模型上记录“time_in”和“time_out”记录。这是我想做但无法开始工作的事情! 检查最后一个时钟条目,看看它是否同时填充了“time_in”和“tim
我想听听您如何解决这种编程任务!?每种类型(OPER = 1 类型)对应一种特定的信息。 这只是大约 10 个具有相同结构的规范之一。首选创建这些“转换器”(协议(protocol))的通用方法。 最
我正在使用 Rest API(NodeJS、Express)和 PostgreSQL 制作 React-Native 应用。 在我的本地机器上托管时一切正常。当 API 托管在我的机器上并且 Post
我是一名优秀的程序员,十分优秀!