myxce/.wolf/bugs/bug-1683.md
2026-10-03 14:51:27 +00:00

3.6 KiB

id status status_updated status_note component severity timestamp last_seen occurrences files tags related fix_commits legacy
bug-1683 fixed 2026-10-03 xceadmin unknown 2026-08-25T00:05:00Z 2026-10-03T07:27:36Z 3
src/xceadmin/src/xcecommon/wire.py
xceadmin
xcecommon
wire-protocol
python
framing
test-failure
unreproducible
bug-1604
362098b1
true

bug-1683: xceadmin pytest failure: test_send_frame_writes_exact_known_good_byte_sequence…

Description

xceadmin pytest failure: test_send_frame_writes_exact_known_good_byte_sequence (src/xceadmin/tests/test_wire.py:200). Test sends a 4-byte payload b'xce!' via wire.send_frame() over a real TLS socket to a raw capture handler that reads exactly 12 bytes (8-byte length header + 4-byte payload) directly off the wire, bypassing this module's own recv_frame() decoder. Expected the captured bytes to be struct.pack('=Q', 4) + b'xce!' (header correctly encodes length=4, followed by the literal payload bytes). Actual captured bytes: the 8-byte header is correct (b'\x04\x00\x00\x00\x00\x00\x00\x00', i.e. length=4 little-endian native uint64_t), but the trailing 4 bytes are all zero (b'\x00\x00\x00\x00') instead of b'xce!' -- the real payload bytes never reached the wire. 1 failed, 266 passed, 3 skipped -- isolated to this one test.

UPDATE (2026-10-03): Correction: the trailing bytes were never zeroed -- pytest's truncated diff showed the 8-byte header alone. See Root cause (test-harness TLS RST race).

Environment

Not recorded (migrated from buglog.json).

Reproduction

Not recorded (migrated from buglog.json).

Root cause

Corrected 2026-10-03, superseding the earlier "not reproducible / build-dir race (bug-1604)" analysis (kept in git history). Test-harness race in src/xceadmin/tests/test_wire.py test_send_frame_writes_exact_known_good_byte_sequence: the client called send_frame() and then sock.close() immediately. Under TLS 1.3 the server sends NewSessionTicket records after the handshake that the client never reads; closing a TCP socket with unread inbound data makes Linux send RST instead of FIN. Each sendall() is its own TLS record, so when the RST lands between the server's read of the 8-byte header record and the 4-byte payload record, the unread payload is discarded and recv() raises ConnectionResetError/BrokenPipeError, which _TlsEchoServer._run swallowed with a bare pass -- leaving captured = header only. The "4 zero bytes" in the original description was a misreading of pytest's truncated diff of the 8-byte header. wire.send_frame() is correct; production paths read the reply before closing and are not exposed.

Fix

test_wire.py only: the client waits on a capture_done Event (set in the handler's finally) before sock.close(); _TlsEchoServer records the handler's OSError in handler_error (asserted None) instead of discarding it; the test is parametrized with settle_s [0.0, 0.05] (immediate / tickets-pending), the 0.05 case being a deterministic regression for the RST path. Fix commit 362098b1.

Verification

  • Test: test_send_frame_writes_exact_known_good_byte_sequence[tickets-pending] in src/xceadmin/tests/test_wire.py — RED before the fix (assert b'\x04\x00...\x00' == b'\x04\x00...xce!'; reviewer's scratch copy without the wait: 5/5 ConnectionResetError 104), GREEN after; 200 looped runs 0 failures; scratch harness 8/2000 natural failures before vs 0/2000 after.
  • Suites: bash src/tools/xce-build.sh xceadmin --incremental 373 passed, 2026-10-03.
  • Live: n/a

References

  • Related: bug-1604