-
Notifications
You must be signed in to change notification settings - Fork 0
Fix guest cmd errors and improve resiliency #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -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): | ||||||||
| 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
|
||||||||
| 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
|
||||||||
| except SystemExit as e: | |
| sys.exit(e.code) | |
| # Let SystemExit propagate naturally; do not catch it here. |
Copilot
AI
Nov 5, 2025
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.