Skip to content

Treat read() returning no bytes as a permanent failure#87

Merged
puddly merged 9 commits into
devfrom
puddly/serial-read-0-on-unplug
May 11, 2026
Merged

Treat read() returning no bytes as a permanent failure#87
puddly merged 9 commits into
devfrom
puddly/serial-read-0-on-unplug

Conversation

@puddly
Copy link
Copy Markdown
Owner

@puddly puddly commented May 10, 2026

Serial ports on POSIX enter a strange state on device disconnect: select will return that n bytes can be read but read(n) returns no bytes. We should enter an instance-wide failure state if this is a case (not just on read) because writes and pin state changes should fail.

Related: home-assistant/core#170257

@codecov
Copy link
Copy Markdown

codecov Bot commented May 10, 2026

Codecov Report

❌ Patch coverage is 97.75281% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.61%. Comparing base (c8be924) to head (8b88c11).
⚠️ Report is 1 commits behind head on dev.

Files with missing lines Patch % Lines
serialx/platforms/serial_rfc2217/__init__.py 85.71% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev      #87      +/-   ##
==========================================
+ Coverage   90.86%   91.61%   +0.75%     
==========================================
  Files          22       22              
  Lines        3482     3603     +121     
==========================================
+ Hits         3164     3301     +137     
+ Misses        318      302      -16     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens disconnect handling by treating “readable but read() returns no bytes” (common on POSIX after device unplug) as a persistent, instance-wide failure. This prevents consumers from silently receiving EOF (b"") and then continuing to write or query/set modem pins against a broken connection.

Changes:

  • Add a persistent “broken” state to serial instances/transports and check it across reads, writes, and modem-pin operations.
  • Treat zero-byte reads as a disconnect on POSIX (sync and asyncio fd-based transports), closing/errored appropriately instead of EOFing.
  • Extend test infrastructure with an “unplug” capability (socat) and add new tests asserting that operations raise after unplug.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_sync_transports.py Adds sync unplug regression test ensuring operations raise after disconnect.
tests/test_async_transports.py Adds async unplug regression tests (AsyncSerial + StreamReader) expecting exceptions after disconnect.
tests/conftest.py Threads unplug callables through the serial_pair fixture.
tests/common.py Adds NO_UNPLUG quirk, extends SerialPair, and upgrades create_socat_pair() to provide unplug callables.
tests/test_serial_linux.py Updates create_socat_pair() tuple unpacking after signature change.
tests/test_serial_esphome.py Updates create_socat_pair() tuple unpacking after signature change.
serialx/common.py Introduces persistent broken-state tracking and enforces it on read/write/modem-pin APIs (sync + transport-side checks).
serialx/platforms/serial_posix.py Marks serial instance broken when a low-level read returns 0 bytes and raises EIO.
serialx/descriptor_transport.py Converts zero-byte fd reads into a broken-state + errored close (prevents busy-looping on b"").
serialx/platforms/serial_rfc2217/init.py Marks RFC2217 as broken on connection close and on TCP connection lost.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread serialx/platforms/serial_rfc2217/__init__.py
Comment thread serialx/platforms/serial_rfc2217/__init__.py
@puddly puddly force-pushed the puddly/serial-read-0-on-unplug branch from a0b44d1 to 487419d Compare May 11, 2026 16:27
@puddly puddly marked this pull request as ready for review May 11, 2026 17:16
@puddly puddly merged commit a59af58 into dev May 11, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants