tts-voice-creator-clone-and.../routes
mARTin-B78 ce3ae79132 Fix streams permanently stuck holding the shared LLM lock (v1.14.2)
Confirmed in production: a streaming attribution/character-sheets
request held _attribution_llm_lock for 11+ minutes, well past its
configured timeout, silently rejecting every subsequent passage as
"Attribution engine busy" and falling back to the non-streaming view -
looking exactly like live-thinking had stopped working, when actually
one earlier request never finished.

Root cause: requests' timeout= on a stream=True call only covers the
connect + first byte, not gaps between later body reads. If the LLM
backend goes silent mid-stream (connection left open, no more chunks),
the blocked socket recv() inside iter_lines() can hang indefinitely.
Since that's a native blocking call, not a Python-level yield point,
neither an in-loop wall-clock check nor GeneratorExit from a
disconnected client can interrupt it - both only take effect at the
next bytecode boundary, which never arrives while blocked in the C
extension.

Added _watchdog_close: a daemon thread that force-closes the upstream
connection if the wrapped block hasn't finished within the configured
timeout. Closing the socket from another thread makes the blocked
recv() raise, unblocking the generator so its normal except/finally
cleanup (including releasing the lock) actually runs. Verified against
the live LLM backend post-restart: stream completes normally with
real token-by-token deltas, and the lock is confirmed free immediately
after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 20:57:49 +02:00
..
__init__.py Security audit, modular refactor, and container-name field 2026-05-29 12:13:07 +02:00
admin.py Release v1.6.0: a11y (WCAG AA), i18n (DE), PWA, perf, tests, Cast UX 2026-06-03 14:23:35 +02:00
characters.py release: v1.12.52 2026-06-30 13:53:08 +02:00
conversation.py Fix streams permanently stuck holding the shared LLM lock (v1.14.2) 2026-07-06 20:57:49 +02:00
docker.py release: v1.12.52 2026-06-30 13:53:08 +02:00
library.py Back user state with SQLite voice index 2026-06-30 15:06:43 +02:00
reader.py Fix casting-feed freeze, zip cast export, character generation prompts (v1.12.90) 2026-07-04 12:48:00 +02:00
rehearsals_db.py release: v1.12.52 2026-06-30 13:53:08 +02:00
settings.py Security audit, modular refactor, and container-name field 2026-05-29 12:13:07 +02:00
sources.py Back user state with SQLite voice index 2026-06-30 15:06:43 +02:00
stt.py Release v1.8.1 2026-06-25 18:48:42 +02:00
tts.py Merge Reader/Casting/Rehearser pipeline into one guided workflow (v1.12.84) 2026-07-03 17:45:38 +02:00