Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 52 additions & 43 deletions guest_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,59 @@
import sys
import json
import os


def run_guest(unix_socket, port, command, use_stdio=True):
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"])

except OSError as e:
if s.error:
import time


def run_guest(unix_socket, port, command, use_stdio=True, max_retries=3, retry_delay=1):

Copilot AI Nov 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing implicit and explicit returns may indicate an error, as implicit returns always return None.

Copilot uses AI. Check for mistakes.
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"])

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)
Comment on lines +44 to +47

Copilot AI Nov 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The retry logic only increments attempt for ConnectionResetError, but the while loop condition checks attempt < max_retries at the start of each iteration. This means after the last retry fails, the loop will execute one more time unnecessarily. Consider moving the increment to the beginning of the loop or adjusting the loop condition.

Copilot uses AI. Check for mistakes.
except OSError as e:
print(f"Socket error: {e}", file=sys.stderr)
else:
print(e, file=sys.stderr)
except SystemExit as e:
# A little janky, but does the trick
sys.exit(e.code)
finally:
s.close()
break
except SystemExit as e:
sys.exit(e.code)
Comment on lines +51 to +52

Copilot AI Nov 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catching and re-raising SystemExit inside the retry loop causes the process to exit on the first retry, preventing any subsequent retry attempts. The SystemExit exception should be re-raised outside the retry loop or handled differently to allow retries to occur.

Suggested change
except SystemExit as e:
sys.exit(e.code)
# Let SystemExit propagate naturally; do not catch it here.

Copilot uses AI. Check for mistakes.
finally:
if s is not None:
s.close()
else:
print("Failed to connect after multiple attempts.", file=sys.stderr)
sys.exit(1)
Comment on lines +56 to +58

Copilot AI Nov 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The while-else clause will execute even when the loop is exited via break statements (lines 43, 51), not just when max_retries is exceeded. This means success cases that break out of the loop will incorrectly trigger the failure message and exit. The else clause should only execute when retries are exhausted.

Copilot uses AI. Check for mistakes.


if __name__ == "__main__":
Expand Down