[otci] drain pending lines in OtCliCommandRunner before timing out (#13494)

In `OtCliCommandRunner.__expect_line()`, asynchronous commands loop
for `timeout` iterations, calling `self.wait(1)` in each step.
Under virtual-time simulation (`VIRTUAL_TIME=1`), `VirtualTime.go()`
advances simulation time without delay when no timer events or radio
traffic are scheduled on the node.

In each iteration, `self.wait(1)` calls `__pending_lines.get_nowait()`.
Because the background reader thread (`__otcli_reader`) transfers
output asynchronously from the subprocess stdout pipe to the queue,
a fast-forwarding simulation can exhaust all timeout iterations in
sub-millisecond wall-clock time before the reader thread has pushed
the buffered lines (such as `Done`) into `__pending_lines`. This
results in an intermittent and spurious `ExpectLineTimeoutError`.

This commit updates `__expect_line()` to drain `__pending_lines` with
a short timeout (0.1s total deadline) after the timeout loop
concludes, giving the reader thread sufficient time to process any
remaining stdout lines before raising `ExpectLineTimeoutError`.

TAG=agy
CONV=9ffc5984-d5ce-4533-ae04-87de08ed9ba7
This commit is contained in:
Jonathan Hui
2026-08-13 10:51:48 -07:00
committed by GitHub
parent 255021a0b9
commit c9d3215b0f
+18
View File
@@ -213,6 +213,24 @@ class OtCliCommandRunner(OTCommandHandler):
done = True
break
if not done:
deadline = time.monotonic() + 0.1
while True:
remaining = deadline - time.monotonic()
if remaining <= 0:
break
try:
line = self.__pending_lines.get(timeout=remaining)
except queue.Empty:
break
output.append(line)
if match_line(line, expect_line):
done = True
break
if not done:
raise ExpectLineTimeoutError(expect_line)