diff --git a/pkgs/clan-cli/clan_cli/cmd.py b/pkgs/clan-cli/clan_cli/cmd.py index cafff882..5650cc70 100644 --- a/pkgs/clan-cli/clan_cli/cmd.py +++ b/pkgs/clan-cli/clan_cli/cmd.py @@ -25,7 +25,10 @@ def handle_output(process: subprocess.Popen, log: Log) -> tuple[str, str]: stdout_buf = b"" stderr_buf = b"" - while len(rlist) != 0: + # Note: We need to read till the process is done, otherwise we might block + # forever because the process might be waiting for us to read from the pipe + # before it can continue and will block in the write call. + while True: r, _, _ = select.select(rlist, [], [], 0) def handle_fd(fd: IO[Any] | None) -> bytes: @@ -33,7 +36,6 @@ def handle_output(process: subprocess.Popen, log: Log) -> tuple[str, str]: read = os.read(fd.fileno(), 4096) if len(read) != 0: return read - rlist.remove(fd) return b"" ret = handle_fd(process.stdout) @@ -48,6 +50,11 @@ def handle_output(process: subprocess.Popen, log: Log) -> tuple[str, str]: sys.stderr.buffer.write(ret) sys.stderr.flush() stderr_buf += ret + + # Check if the process is still running + if process.poll() is not None: + break + return stdout_buf.decode("utf-8"), stderr_buf.decode("utf-8") diff --git a/pkgs/clan-cli/clan_cli/secrets/generate.py b/pkgs/clan-cli/clan_cli/secrets/generate.py index 46813a60..27d815bd 100644 --- a/pkgs/clan-cli/clan_cli/secrets/generate.py +++ b/pkgs/clan-cli/clan_cli/secrets/generate.py @@ -1,10 +1,9 @@ import argparse import logging import os -import subprocess import sys -from clan_cli.errors import ClanError +from clan_cli.cmd import Log, run from ..machines.machines import Machine @@ -17,15 +16,14 @@ def generate_secrets(machine: Machine) -> None: env["PYTHONPATH"] = ":".join(sys.path) # TODO do this in the clanCore module print(f"generating secrets... {machine.generate_secrets}") - proc = subprocess.run( + run( [machine.generate_secrets], env=env, + error_msg="failed to generate secrets", + log=Log.BOTH, ) - if proc.returncode != 0: - raise ClanError("failed to generate secrets") - else: - print("successfully generated secrets") + print("successfully generated secrets") def generate_command(args: argparse.Namespace) -> None: