Skip to content
Merged
Show file tree
Hide file tree
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
11 changes: 9 additions & 2 deletions src/rdc/services/session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,15 @@ def open_session(
max_attempts = 1 if remote_url is not None else 3
host = "127.0.0.1"
detail = "unknown error"
started = False
for _attempt in range(max_attempts):
port = pick_port()
token = secrets.token_hex(16)
proc = start_daemon(str(capture), port, token, remote_url=remote_url, gpu=gpu)

ok, detail = wait_for_ping(host, port, token, timeout_s=resolved_timeout, proc=proc)
if ok:
started = True
break
proc.terminate()
try:
Expand All @@ -207,9 +209,14 @@ def open_session(
proc.kill()
proc.wait()
stderr = _read_daemon_stderr(proc)
timed_out = detail.startswith("timeout")
if stderr:
detail = stderr
else:
# Keep the real reason (timeout, exit code) first; the log tail is context.
detail = f"{detail}; daemon log: {stderr}"
if timed_out:
detail += "; large captures may need a longer --timeout (or RDC_OPEN_TIMEOUT)"
break
if not started:
return False, f"error: daemon failed to start ({detail}) -- hint: run 'rdc doctor'"

_discard_daemon_stderr(proc)
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,33 @@ def test_open_session_all_retries_fail(monkeypatch: pytest.MonkeyPatch, tmp_path
assert "rdc doctor" in msg


def test_open_session_timeout_reports_timeout_first_and_does_not_retry(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
"""A startup timeout leads the message, keeps the log as context, and is not retried."""
monkeypatch.delenv("RDC_SESSION", raising=False)
monkeypatch.setattr(session_service, "load_session", lambda: None)
monkeypatch.setattr(session_service, "_renderdoc_available", lambda: False)

log = tmp_path / "daemon.stderr"
log.write_text("GPU match fallback: choosing NVIDIA\n")
mock_proc = MagicMock()
mock_proc.pid = 999
mock_proc._rdc_stderr_path = str(log)
starts: list[int] = []
monkeypatch.setattr(
session_service, "start_daemon", lambda *a, **kw: starts.append(1) or mock_proc
)
monkeypatch.setattr(session_service, "wait_for_ping", lambda *a, **kw: (False, "timeout (15s)"))

ok, msg = session_service.open_session(Path("test.rdc"))
assert ok is False
assert len(starts) == 1
assert msg.startswith("error: daemon failed to start (timeout (15s);")
assert "--timeout" in msg
assert msg.index("timeout (15s)") < msg.index("GPU match fallback")


def test_close_session_fallback_kill_on_shutdown_error(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
Expand Down
Loading