ch-runner: move wait() out of run_ch

This commit is contained in:
Else Someone 2026-02-23 22:32:32 +02:00
parent 04befb6328
commit 8d1324da03

View file

@ -355,6 +355,16 @@ in
return args_mut return args_mut
def alive_after(proc, timeout):
if proc.returncode is not None:
return False
try:
proc.wait(timeout)
except subprocess.TimeoutExpired:
return True
return False
class Processes: class Processes:
def __init__(self, prefix, vm, check=True, **defaults): def __init__(self, prefix, vm, check=True, **defaults):
self.prefix = prefix self.prefix = prefix
@ -392,6 +402,7 @@ in
}, },
) )
@contextmanager
def popen(self, *args, **kwargs): def popen(self, *args, **kwargs):
kwargs["pass_fds"] = kwargs.get("pass_fds", ()) kwargs["pass_fds"] = kwargs.get("pass_fds", ())
kwargs["env"] = kwargs.get("env", self.make_env()) kwargs["env"] = kwargs.get("env", self.make_env())
@ -399,11 +410,20 @@ in
kwargs["stdin"] = kwargs.get("stdin", subprocess.DEVNULL) kwargs["stdin"] = kwargs.get("stdin", subprocess.DEVNULL)
kwargs["stdout"] = kwargs.get("stdout", subprocess.DEVNULL) kwargs["stdout"] = kwargs.get("stdout", subprocess.DEVNULL)
kwargs["stderr"] = kwargs.get("stderr", subprocess.DEVNULL) kwargs["stderr"] = kwargs.get("stderr", subprocess.DEVNULL)
return subprocess.Popen( try:
proc = subprocess.Popen(
args, args,
**kwargs, **kwargs,
) )
yield proc
finally:
try:
proc.wait(0.125)
except subprocess.TimeoutExpired:
proc.terminate()
proc.wait()
@contextmanager
def bwrap( def bwrap(
self, self,
*bwrap_args, *bwrap_args,
@ -447,7 +467,10 @@ in
bwrap_args_sock, remote = socket.socketpair() bwrap_args_sock, remote = socket.socketpair()
remote.set_inheritable(True) remote.set_inheritable(True)
bwrap_args_f = bwrap_args_sock.makefile("w") bwrap_args_f = bwrap_args_sock.makefile("w")
with closing(bwrap_args_sock), closing(bwrap_args_f): with ExitStack() as cleanup:
# cleanup.enter_context(closing(bwrap_args_sock))
# cleanup.enter_context(closing(bwrap_args_f))
def print_arg(*args): def print_arg(*args):
print(*args, file=bwrap_args_f, sep="\0", end="\0") print(*args, file=bwrap_args_f, sep="\0", end="\0")
@ -491,15 +514,17 @@ in
bwrap_args_f.flush() bwrap_args_f.flush()
with closing(remote): with ExitStack() as es:
proc = self.popen( es.enter_context(closing(remote))
es.enter_context(closing(bwrap_args_sock))
es.enter_context(closing(bwrap_args_f))
proc = cleanup.enter_context(self.popen(
"bwrap", "--args", str(remote.fileno()), *bwrap_args, "bwrap", "--args", str(remote.fileno()), *bwrap_args,
**popen_kwargs, **popen_kwargs,
executable=BWRAP_PATH, executable=BWRAP_PATH,
pass_fds=(*pass_fds, remote.fileno()), pass_fds=(*pass_fds, remote.fileno()),
) ))
yield proc
return proc
@contextmanager @contextmanager
def run_ch(self): def run_ch(self):
@ -520,7 +545,8 @@ in
"fd=0", "fd=0",
# f"fd={s.fileno()}" # f"fd={s.fileno()}"
] ]
p = self.bwrap( needs_cleanup = False
with self.bwrap(
*args, *args,
bind=[self.prefix], bind=[self.prefix],
# Probably just need the path to vmlinux # Probably just need the path to vmlinux
@ -529,28 +555,17 @@ in
shell=False, shell=False,
stderr=None, stderr=None,
# pass_fds=(s.fileno(),) # pass_fds=(s.fileno(),)
) ) as proc:
# s.close() # s.close()
try: assert alive_after(proc, 0.125)
p.wait(0.125)
needs_cleanup = False
except subprocess.TimeoutExpired:
needs_cleanup = True
if not os.path.exists(self.prefix + "/vmm.sock"): if not os.path.exists(self.prefix + "/vmm.sock"):
raise RuntimeError( raise RuntimeError(
f"{self.prefix}/vmm.sock should exist by now") f"{self.prefix}/vmm.sock should exist by now")
if p.returncode is not None: needs_cleanup = True
if proc.returncode is not None:
raise RuntimeError("CH exited early") raise RuntimeError("CH exited early")
yield p yield proc
finally: finally:
try:
p.poll()
except: # noqa: E722
pass
if p.returncode is None:
print("Terminating CH")
p.terminate() # CH handles SIG{INT,TERM}?
p.wait()
unlink_paths = [ unlink_paths = [
self.prefix + "/vmm.sock", self.prefix + "/vmm.sock",
self.prefix + "/vmm.sock.lock", self.prefix + "/vmm.sock.lock",
@ -621,13 +636,9 @@ in
# "pass_fds": (2, s.fileno()), # "pass_fds": (2, s.fileno()),
} }
proc_ctx = self.popen(*args, **kwargs) with self.popen(*args, **kwargs) as p:
with proc_ctx as p:
try: try:
try: assert alive_after(p, 0.125)
p.wait(0.125)
except subprocess.TimeoutExpired:
pass
if p.returncode is not None: if p.returncode is not None:
raise RuntimeError("virtiofsd exited too early") raise RuntimeError("virtiofsd exited too early")
yield p, sock_path yield p, sock_path