From 07c4f0b3423cca06ef9e75c9bb09d299160868f0 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 5 Nov 2025 12:21:01 -0500 Subject: [PATCH 1/3] fix: guest_cmd error --- guest_cmd.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/guest_cmd.py b/guest_cmd.py index bb86306..e2c5942 100644 --- a/guest_cmd.py +++ b/guest_cmd.py @@ -6,6 +6,7 @@ def run_guest(unix_socket, port, command, use_stdio=True): + s = None try: s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(unix_socket) @@ -38,15 +39,13 @@ def run_guest(unix_socket, port, command, use_stdio=True): sys.exit(result["exit_code"]) except OSError as e: - if s.error: - print(f"Socket error: {e}", file=sys.stderr) - else: - print(e, file=sys.stderr) + print(f"Socket error: {e}", file=sys.stderr) except SystemExit as e: # A little janky, but does the trick sys.exit(e.code) finally: - s.close() + if s is not None: + s.close() if __name__ == "__main__": From b60644900facb44b117ff9cf14606bc9964e35a5 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 5 Nov 2025 12:22:36 -0500 Subject: [PATCH 2/3] make guest_cmd resilient to connection resets --- guest_cmd.py | 95 +++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/guest_cmd.py b/guest_cmd.py index e2c5942..4bfac29 100644 --- a/guest_cmd.py +++ b/guest_cmd.py @@ -3,49 +3,60 @@ import sys import json import os - - -def run_guest(unix_socket, port, command, use_stdio=True): - s = None - try: - s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - s.connect(unix_socket) - s.settimeout(None) # Disable timeout for long-running commands - - # Send CONNECT PORTNUM (for vsock) followed by the actual command - connect_command = f"CONNECT {port}\n" - s.sendall(connect_command.encode('utf-8')) - response = s.recv(4096).decode('utf-8') - assert f"OK {port}" in response, "OK not received from vsock unix socket" - - s.sendall(command.encode('utf-8')) - - output = b"" - while True: - chunk = s.recv(4096) - if not chunk: +import time + + +def run_guest(unix_socket, port, command, use_stdio=True, max_retries=3, retry_delay=1): + attempt = 0 + while attempt < max_retries: + s = None + try: + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(unix_socket) + s.settimeout(None) # Disable timeout for long-running commands + + # Send CONNECT PORTNUM (for vsock) followed by the actual command + connect_command = f"CONNECT {port}\n" + s.sendall(connect_command.encode('utf-8')) + response = s.recv(4096).decode('utf-8') + assert f"OK {port}" in response, "OK not received from vsock unix socket" + + s.sendall(command.encode('utf-8')) + + output = b"" + while True: + chunk = s.recv(4096) + if not chunk: + break + output += chunk + + received_json = output.decode('utf-8') + result = json.loads(received_json) + + if not use_stdio: + return result["stdout"] + print(result["stdout"], end='') + # Propagate stderr to stderr + if result["stderr"]: + print(result["stderr"], file=sys.stderr, end='') + sys.exit(result["exit_code"]) + break # Success, exit loop + + except ConnectionResetError as e: + print(f"Connection reset by peer (attempt {attempt+1}/{max_retries}): {e}", file=sys.stderr) + attempt += 1 + time.sleep(retry_delay) + except OSError as e: + print(f"Socket error: {e}", file=sys.stderr) break - output += chunk - - received_json = output.decode('utf-8') - result = json.loads(received_json) - - if not use_stdio: - return result["stdout"] - print(result["stdout"], end='') - # Propagate stderr to stderr - if result["stderr"]: - print(result["stderr"], file=sys.stderr, end='') - sys.exit(result["exit_code"]) - - except OSError as e: - print(f"Socket error: {e}", file=sys.stderr) - except SystemExit as e: - # A little janky, but does the trick - sys.exit(e.code) - finally: - if s is not None: - s.close() + except SystemExit as e: + sys.exit(e.code) + finally: + if s is not None: + s.close() + else: + print("Failed to connect after multiple attempts.", file=sys.stderr) + sys.exit(1) if __name__ == "__main__": From 306c028c95406d17a65558fad8bc0964a50dae67 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 5 Nov 2025 14:17:59 -0500 Subject: [PATCH 3/3] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- guest_cmd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/guest_cmd.py b/guest_cmd.py index 4bfac29..53c6f29 100644 --- a/guest_cmd.py +++ b/guest_cmd.py @@ -40,7 +40,6 @@ def run_guest(unix_socket, port, command, use_stdio=True, max_retries=3, retry_d if result["stderr"]: print(result["stderr"], file=sys.stderr, end='') sys.exit(result["exit_code"]) - break # Success, exit loop except ConnectionResetError as e: print(f"Connection reset by peer (attempt {attempt+1}/{max_retries}): {e}", file=sys.stderr)