Skip to content

Ryanontheinside/feat/models/rt input#235

Merged
leszko merged 4 commits into
mainfrom
ryanontheinside/feat/models/rt-input
Jun 11, 2026
Merged

Ryanontheinside/feat/models/rt input#235
leszko merged 4 commits into
mainfrom
ryanontheinside/feat/models/rt-input

Conversation

@ryanontheinside

Copy link
Copy Markdown
Collaborator

No description provided.

@ryanontheinside ryanontheinside force-pushed the ryanontheinside/feat/models/rt-input branch from 0992b10 to aa283c4 Compare June 10, 2026 02:59
@ryanontheinside ryanontheinside force-pushed the ryanontheinside/feat/models/rt-input branch from aa283c4 to ef90b23 Compare June 10, 2026 15:17
…io recv hardening

Two server-side halves of the rt-input deadlock (the client halves are
rtmg-vst#33), both reproduced and validated live against the :dev pod:

1. websockets-sync holds protocol_mutex across socket.sendall, and
   recv_events — the thread that reads EVERY inbound frame — needs the
   same mutex. A single 11 MB stem send therefore froze all reads until
   the peer drained it; against a VST mid write_audio upload (its own
   reads gated behind its sends, see rtmg-vst#33) the two sides wedged
   permanently: params dead, splices never received, keepalive killed
   the session (1011 via the tunnel). Thread dump of the live wedge:
   conn_handler in sendall holding protocol_mutex; recv_events and
   keepalive blocked acquiring it. Big payloads (stems, the post-swap
   source mirror, slice frames) now go out as fragmented messages in
   ~256 KiB pieces — the mutex releases between fragments so reads
   interleave and the cycle cannot form. Fragmentation is invisible at
   the message layer; payload bytes are identical.

2. write_audio's binary payload was read with a bare blocking recv and
   no type check: an orphan header consumed the NEXT JSON command as
   its payload (audio_write_failed: "a bytes-like object is required,
   not 'str'"), and a payload that never arrived blocked the recv loop
   forever — wedging the whole session. The read now has a 10 s timeout
   and a bytes type check; both failure modes answer audio_write_failed
   and keep the session alive.

The chunked-send half also applies to main (stem delivery freezes reads
there too, e.g. against a swap upload in flight) and is worth
cherry-picking independently of rt-input.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
leszko and others added 2 commits June 11, 2026 12:05
…d reads

Review fixes for #245:

- The post-swap source mirror in _serialize_swap_ready was still a plain
  ws.send of a full-length f16 buffer (tens of MB) — the largest single
  payload on the wire and exactly the read-freezing sendall this PR
  exists to eliminate. It now goes through chunked_ws_send.
- The 10 s timeout + binary type check added for write_audio now covers
  set_timbre_source, set_structure_source, and the client-upload arm of
  swap_source via a shared _recv_binary_payload helper — same orphan-
  header wedge class, same graceful *_failed answer. The not-binary log
  includes a preview of the consumed frame so a dropped JSON command is
  traceable.
- The control-bus recv thunk accepts (and ignores) the timeout kwarg, so
  the TypeError fallback around recv_audio(timeout=10) is gone — it
  fired on every MCP-injected write_audio in production and could mask a
  genuine TypeError from inside ws.recv.
- chunked_ws_send: rename the _chunk param to chunk_size and annotate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arvation

fix(rtmg/web): bulk sends freeze all reads — chunked sends + write_audio recv hardening
@leszko leszko marked this pull request as ready for review June 11, 2026 10:15
@leszko leszko merged commit 76dac9c into main Jun 11, 2026
@leszko leszko deleted the ryanontheinside/feat/models/rt-input branch June 11, 2026 10:15
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.

3 participants