fix: compute instrument read timeout before sending the read command

The previous fix computed the host-side wait (via a read_tmo_ms query)
after already sending "++read eoi" -- but the controller doesn't answer
any further command while that read is outstanding, so the read_tmo_ms
query itself raced the read it was meant to be timing and could time
out. Reordered so the timeout is resolved first in both query() and
read(); added a regression test pinning the wire ordering.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 18:55:26 -05:00
parent b35864656a
commit 97a632435d
2 changed files with 26 additions and 2 deletions

View File

@@ -67,6 +67,21 @@ def test_status_and_lon_raise_in_controller_mode(fake_gpib_server):
_ = ctrl.lon
def test_query_fetches_read_tmo_ms_before_sending_read_eoi(fake_gpib_server):
# Regression test: found against real hardware that the controller
# doesn't answer any further command while a "++read" it issued is
# still outstanding (waiting for EOI or its own read_tmo_ms timeout).
# So query()/read() must fetch read_tmo_ms (to size the host-side wait)
# *before* sending "++read eoi" -- fetching it after races the read
# it's meant to be timing. Assert that ordering on the wire.
server, tcp_server = fake_gpib_server
with GpibController.ethernet(tcp_server.host, tcp_server.port) as ctrl:
ctrl.query("*IDN?", read_timeout=None)
assert _wait_until(lambda: b"++read eoi" in server.raw_received)
raw = bytes(server.raw_received)
assert raw.index(b"++read_tmo_ms") < raw.index(b"++read eoi")
def test_status_and_spoll_return_bits_with_rqs_at_index_6(fake_gpib_server):
server, tcp_server = fake_gpib_server
server.state["mode"] = "0" # DEVICE