Dispatcharr/apps
firestaerter3 5ad4824c4b fix(vod-proxy): eliminate profile_connections counter stuck-at-nonzero races
Three race conditions in multi_worker_connection_manager could leave
the Redis profile_connections:<id> counter permanently elevated with no
active streams, causing all VOD requests to 503 "All profiles at capacity".

Bug 1 — decrement_active_streams() return value was ignored
All three generator exit paths (normal, GeneratorExit, Exception) called
decrement_active_streams() and unconditionally set decremented = True
regardless of whether the lock was acquired. On lock contention the decrement
was silently skipped, active_streams remained > 0, the subsequent
has_active_streams() check returned True, and _decrement_profile_connections()
was never called. The counter was then stuck until manual DEL.

Fix: add decrement_active_streams_and_check() which performs the decrement and
the "are there remaining streams?" check atomically under a single lock,
eliminating the race window. All three exit paths and the finally block now
use this method and propagate its success/remaining return values.

Bug 2 — non-atomic GET-then-DECR in _decrement_profile_connections()
The previous implementation read the counter with GET then conditionally
called DECR. Two concurrent decrements could both pass the > 0 guard and
both fire, driving the counter to -1. A subsequent _check_and_reserve_profile_slot()
INCR would then produce 0 which passes the <= max_streams check, allowing
an extra stream to bypass the limit on the next request.

Fix: replace GET-then-DECR with a direct DECR (matching the INCR-first
pattern already used by _check_and_reserve_profile_slot) and clamp the
result to 0 if it goes negative.

Bug 3 — has_active_streams() read state without holding the lock
The separate has_active_streams() call after decrement_active_streams()
released its lock left a window where another concurrent stream could
increment active_streams back to 1, causing the profile decrement to be
skipped. This is resolved as a consequence of Bug 1's fix: the new
decrement_active_streams_and_check() method reads active_streams while
the lock is still held, eliminating the window entirely.

Adds tests covering all three scenarios in
apps/proxy/vod_proxy/tests/test_profile_connections.py.

Fixes #1121.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:23:36 +01:00
..
accounts Cleanup frontend and backend if valid item ids change. 2026-03-08 17:05:26 -05:00
api initial connect feature 2026-02-08 09:29:22 -05:00
backups Fix #954: Superuser detection; Feature #1004: User account disable/enable 2026-02-22 18:05:02 -06:00
channels Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/CodeBormen/943 2026-03-08 18:04:11 -05:00
connect Migrations: Add missing migrations. 2026-02-26 13:25:51 -06:00
dashboard modified database fields for consistency, removed custom_url from streams (no longer needed) 2025-03-16 09:07:10 -04:00
epg Merge pull request #1072 from CodeBormen/feat/1065-Add-Subtitle-and-Season-Episode-to-Guide 2026-03-13 16:48:20 -05:00
hdhr - Swagger/OpenAPI Migration: Migrated from drf-yasg (OpenAPI 2.0) to drf-spectacular (OpenAPI 3.0) for API documentation. This provides: 2026-01-27 13:33:33 -06:00
m3u Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/JCBird1012/1062 2026-03-08 12:00:46 -05:00
output Enhancement: EPG output when no days parameter is specified now excludes already-ended programs instead of returning all historical data. 2026-03-05 12:31:36 -06:00
plugins added event support to plugins 2026-02-11 19:50:11 -05:00
proxy fix(vod-proxy): eliminate profile_connections counter stuck-at-nonzero races 2026-03-19 23:23:36 +01:00
vod Bug Fix: VOD orphan cleanup crashing with a ForeignKeyViolation (IntegrityError) when a concurrent refresh task created a new M3UMovieRelation or M3USeriesRelation for a movie/series between the orphan-detection query and the DELETE SQL. Both orphaned_movies.delete() and orphaned_series.delete() are now wrapped in try/except IntegrityError; affected records are skipped with a warning and will be cleaned up on the next scheduled run. 2026-03-08 11:56:52 -05:00