如何用subprocess在超时后终止perf record及其子进程?
解决subprocess终止perf时无法连带终止其子进程yes的问题
问题原因
subprocess.run的timeout参数仅会终止主进程(perf),但perf启动的子进程yes会脱离父进程成为孤儿进程,被系统进程收养后继续运行。而终端中按Ctrl+C是向整个进程组发送SIGINT信号,因此perf和yes会同时收到信号并终止。
解决方案
要实现和终端Ctrl+C相同的效果,需要让perf及其子进程同属一个进程组,然后向整个进程组发送终止信号。
方法一:使用Popen+进程组信号
import subprocess import os import signal import time # 启动perf并创建独立进程组,让其子进程自动加入该组 proc = subprocess.Popen(['perf', 'record', 'yes'], preexec_fn=os.setpgrp) time.sleep(1) # 模拟1秒超时 # 向整个进程组发送SIGINT信号,等同于终端Ctrl+C os.killpg(os.getpgid(proc.pid), signal.SIGINT) proc.wait() # 等待进程退出并回收资源
方法二:结合timeout捕获与进程组信号
如果需要保留超时逻辑,可捕获TimeoutExpired异常后发送进程组信号:
import subprocess import os import signal proc = subprocess.Popen(['perf', 'record', 'yes'], preexec_fn=os.setpgrp) try: proc.wait(timeout=1) except subprocess.TimeoutExpired: os.killpg(os.getpgid(proc.pid), signal.SIGINT) proc.wait()
关键说明
preexec_fn=os.setpgrp:让perf进程成为新进程组的组长,后续perf启动的子进程(如yes)会自动加入该进程组。os.killpg:向指定进程组的所有成员发送信号,确保perf和yes同时收到终止信号。
内容的提问来源于stack exchange,提问作者Kerrick Staley
相关产品推荐
相关产品推荐

