Skip to content

Commit

Permalink
pw_emu: Better handling for startup errors
Browse files Browse the repository at this point in the history
When using qemu with an invalid argument the command fails with a JSON
decode error because the qemu process terminates before the qmp
handshake is completed.

Catch these kind of errors and surface them to the user as start
errors. Also provide additional context by dumping the emulator logs.

Bug: 315868463
Change-Id: I07248dc3f27b7b6096fed829a71c0079eae46616
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/184859
Reviewed-by: Jonathon Reinhart <[email protected]>
Pigweed-Auto-Submit: Octavian Purdila <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
  • Loading branch information
tavip authored and CQ Bot Account committed Dec 14, 2023
1 parent 82c82d9 commit f0c03bb
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pw_emu/py/pw_emu/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ def main() -> int:
)

try:
emu = Emulator(args.working_dir, args.config)
emu = Emulator(Path(args.working_dir), args.config)
args.func(emu, args)
except Error as err:
print(err)
Expand Down
18 changes: 17 additions & 1 deletion pw_emu/py/pw_emu/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ class RunError(Error):

def __init__(self, proc: str, msg: str) -> None:
super().__init__(f'error running `{proc}`: {msg}')
self.proc = proc
self.msg = msg


class InvalidPropertyPath(Error):
Expand Down Expand Up @@ -582,6 +584,12 @@ def get_channel_stream(
def get_channels(self) -> List[str]:
return self._handles.channels.keys()

def get_logs(self) -> str:
"""Returns the emulator logs."""

log_path = self._wdir / f'{self._handles.emu}.log'
return log_path.read_text()

def stop(self) -> None:
"""Stops the emulator."""

Expand Down Expand Up @@ -949,7 +957,15 @@ def start(
self._stop_procs()
raise err

self._post_start()
try:
self._post_start()
except RunError as err:
self._handles.save(wdir)
connector = self._get_connector(self._wdir)
if not connector.running():
msg = err.msg + '; dumping logs:\n' + connector.get_logs()
raise RunError(err.proc, msg)
raise err
self._handles.save(wdir)

if proc:
Expand Down
11 changes: 9 additions & 2 deletions pw_emu/py/pw_emu/qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
Launcher,
Error,
InvalidChannelType,
RunError,
WrongEmulator,
)

Expand Down Expand Up @@ -290,9 +291,15 @@ def _pre_start(

def _post_start(self) -> None:
assert self._qmp_init_sock is not None
conn, _ = self._qmp_init_sock.accept()
try:
conn, _ = self._qmp_init_sock.accept()
except (KeyboardInterrupt, socket.timeout):
raise RunError('qemu', 'qmp connection failed')
self._qmp_init_sock.close()
qmp = QmpClient(conn.makefile('rwb', buffering=0))
try:
qmp = QmpClient(conn.makefile('rwb', buffering=0))
except json.decoder.JSONDecodeError:
raise RunError('qemu', 'qmp handshake failed')
conn.close()

resp = qmp.request('query-chardev')
Expand Down
5 changes: 3 additions & 2 deletions pw_emu/py/pw_emu/renode.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@

from pw_emu.core import (
Connector,
Error,
Handles,
InvalidChannelType,
Launcher,
Error,
RunError,
WrongEmulator,
)

Expand Down Expand Up @@ -155,7 +156,7 @@ def _post_start(self) -> None:
if not connected:
msg = 'failed to connect to robot channel'
msg += f'({robot.host}:{robot.port}): {err}'
raise RenodeRobotError(msg)
raise RunError('renode', msg)

sock.close()

Expand Down

0 comments on commit f0c03bb

Please sign in to comment.