subprocess在IC验证中的应用
专栏:ExASIC Nov. 10, 2024, 2:04 p.m. 85 阅读
`subprocess.Popen`相比于`os.system()`多了很多可控制的参数,用起来更灵活。这里记录两段代码,一段是超时退出仿真,另一段代码是检测到Ctrl-C后自动结束所有的仿真进程。

subprocess.Popen相比于os.system()多了很多可控制的参数,用起来更灵活。这里记录两段代码,一段是超时退出仿真,另一段代码是检测到Ctrl-C后自动结束所有的仿真进程。

1. 仿真超时

遇到的坑:在shell=True时,p.kill()、p.terminate()会失效。看起来只是把shell进程给结束掉了,shell的子进程ncsim却还在。

经过大神的帮助和查阅stackoverflow相关帖子后,找到下面一个可行的方案。简单来说就是用process group,把所有进程、子进程全总绑定到session_id。

使用时需要注意以下几点:

  1. shell=True

  2. preexec_fn=os.setsid

  3. os.killpg(os.getpgid(p.pid), signal.SIGTERM)

代码如下:

def _run(cmd, stdout=None, timeout=600):
    ret = "timeout"
    
    p = subprocess.Popen(cmd,
                         stdout=stdout,
                         shell=True,
                         preexec_fn=os.setsid) #new session id

    try:
        t_start = time.time()
        while True:
            time.sleep(5)
            
            if p.poll() is None: #timeout exit
                dt = time.time() - t_start
                if dt > timeout:
                    #kill all processes attched to this session id
                    os.killpg(os.getpgid(p.pid), signal.SIGTERM) 
                    ret = "timeout"
                    return ret
                
            else: #normal exit
                ret = "done"
                return ret

2. 检测Ctrl-C自动Kill所有子进程

其实方法就是上面的process group。在except KeyboardInterrupt里发送signal.SIGTERM就可以了。

except KeyboardInterrupt as e:
        print(e)
        os.killpg(os.getpgid(p.pid), signal.SIGTERM)
        ret = "ctrl_c"

这个方法也适用于结束multiprocessing.pool启动的子进程。

multiprocessing相关的内容可以参考这里:multiprocessing在并行仿真中的应用

感谢阅读,更多文章点击这里:【专栏:ExASIC】
最新20篇 开设专栏