Skip to content

fix: remove flush() in _write_frame to prevent hang on USB CDC ACM#77

Closed
jirogit wants to merge 1 commit into
pyMC-dev:mainfrom
jirogit:fix/kiss-flush-hang-usb-cdc
Closed

fix: remove flush() in _write_frame to prevent hang on USB CDC ACM#77
jirogit wants to merge 1 commit into
pyMC-dev:mainfrom
jirogit:fix/kiss-flush-hang-usb-cdc

Conversation

@jirogit
Copy link
Copy Markdown

@jirogit jirogit commented May 24, 2026

Summary

  • serial.flush() calls termios.tcdrain() internally, which blocks indefinitely on USB CDC ACM devices (e.g. ESP32 T3S3/S3 with TinyUSB) on Linux
  • Confirmed on Linux Mint + T3S3 + MeshCore KISS Modem built from upstream/dev
  • pyserial's write() already copies data into the kernel USB buffer atomically — no explicit drain is needed

Root Cause

pyserial's Serial.flush() calls termios.tcdrain() on POSIX systems. For native UART devices tcdrain() returns promptly, but USB CDC ACM character devices (backed by TinyUSB on ESP32) do not implement the tcdrain completion signal, causing it to hang indefinitely.

Fix

Replace the flush() try/except block with a comment explaining why it was removed:

# flush()/tcdrain() removed: hangs indefinitely on USB CDC ACM
# (e.g. ESP32 T3S3/S3 with TinyUSB). write() already copies data
# to the kernel USB buffer atomically; no drain needed.

Test Plan

  • Connect ESP32 T3S3 via USB CDC ACM (/dev/ttyACM0)
  • Run KissModemWrapper.connect() and verify it no longer hangs in _write_frame()
  • Confirm frame TX and RX operate normally
  • Verify no regression on native UART devices (e.g. /dev/ttyUSB0 with CH340/CP2102)

Tested:

  • Linux Mint + ESP32 T3S3 (USB CDC ACM /dev/ttyACM1)
  • MeshCore KISS Modem firmware built from upstream/dev branch (commit around 2026-05-23)
  • Without fix: hangs indefinitely after "KISS modem connected" log
  • With fix: initialization completes, packets received and visible in pyMC_Repeater dashboard

serial.flush() calls termios.tcdrain() under the hood, which blocks
indefinitely on USB CDC ACM devices (e.g. ESP32 T3S3/S3 with TinyUSB)
on Linux. Confirmed on Linux Mint + T3S3 + MeshCore KISS Modem v1.15.0.
pyserial's write() already copies data into the kernel USB buffer
atomically, so no explicit drain is needed.
@jirogit
Copy link
Copy Markdown
Author

jirogit commented May 24, 2026

Closing: could not reliably reproduce the hang on T3S3. Reproduction conditions are unclear — the installed venv had already been manually patched, and pymc-repeater ran normally with flush() present. Reopening if a reliable reproduction case is identified.

@jirogit jirogit closed this May 24, 2026
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.

1 participant