在 Python 中创建处于挂起状态的子进程



我可以在Python中创建一个子进程并像这样挂起它:

proc = subprocess.pOpen(['binary', 'arg1', 'arg2'])
# Subprocess was created in a running state
proc_handle = psutil.Process(pid=proc.pid)
proc_handle.suspend()
# Subprocess is now suspended
proc_handle.resume()
# Subprocess is now running

问:如何在挂起状态下启动子进程?我知道创建子流程和暂停子流程之间的时间很少,但我对无缝解决方案感兴趣。另外,我知道我可以轻松地将子进程包装在父进程中,该父进程将在继续之前等待恢复信号,但如果存在的话,我想要一个不那么笨拙、更优雅的解决方案。此外,我知道我可以围绕子进程创建一个类包装器,直到我真正想要运行它才会创建它,但是我还没有为它分配 PID,我将无法检查统计信息,例如未启动进程的内存占用。

如果我能做到这一点,我会喜欢它:

cmd = ['binary', 'arg1', 'arg2']
proc = subprocess.pOpen(cmd, autostart=False) # autostart argument does not exist
# Subprocess was created, so it had a PID and has a memory footprint, 
# but is suspended and no code had been run

当我使用 autostart=False 编写上述 pOpen 示例时,我意识到由于进程的运行方式,这可能是不可能的。如果我想在 main() 函数开始时中断,那么一些代码已经作为静态初始化的一部分执行了。理想情况下,子进程将在该步骤之前暂停,就在创建和初始化进程内存之后。

注意:我对在 linux 环境中解决此问题特别感兴趣,但如果存在独立于平台的解决方案,那就太好了。

fork()之后停止,在exec()之前

这个很简单,虽然不是那么有用:

import subprocess, os, signal
proc = subprocess.Popen(
['binary', 'arg1', 'arg2'],
preexec_fn=lambda: os.kill(os.getpid(), signal.SIGSTOP),
)

为什么"没那么有用"?因为当preexec_fn在新的 PID 中运行时,您的意图似乎涉及收集有关内存使用情况的统计信息(在某种程度上,可以在程序执行其malloc()调用之前完成),并且在exec发生之前,您将测量其内存的程序是 Python 解释器。


exec()之后停止,在调用main()之前

首先,为 Linux 加载程序编译一个审计模块 (ld.so),类似于以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
unsigned int la_version(unsigned int version) {
return version;
}
/* To have stronger guarantees of immediacy, I might replace this with flock()ing a
* lockfile, and releasing that lock from the parent when ready to continue. YMMV,
* consider this a stub intended to be replaced.
*/
void la_preinit(uintptr_t *cookie) {
kill(getpid(), SIGSTOP);
unsetenv("LD_AUDIT");        /* avoid our children getting stopped the same way */
}

然后,在运行子进程时指定它:

newEnv = dict(os.environ)
newEnv['LD_AUDIT'] = '/path/to/above/library.so'
proc = subprocess.Popen(['binary', 'arg1', 'arg2'], env=newEnv)

加载程序在启动之前调用la_preinitmain()

最新更新