mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-18 00:55:50 +00:00
Three interrelated bugs cause TS proxy streams to terminate prematurely in multi-worker uWSGI deployments: 1. Double ProxyServer instantiation: ProxyConfig.ready() in apps/proxy/apps.py calls TSProxyServer() directly, bypassing get_instance(). The subsequent TSProxyConfig.ready() call to get_instance() creates a second instance. Each instance starts its own cleanup thread, but only one holds channel data — the orphaned cleanup thread cannot extend ownership. 2. Redis flushdb() on every client init: RedisClient.get_client() in core/utils.py calls flushdb() whenever a new connection is created. Celery autoscale workers spawning mid-stream nuke all Redis keys including ownership, client records, and channel metadata. 3. No recovery from expired ownership: get_channel_owner() has a TOCTOU bug (two separate GET calls in a lambda). extend_ownership() silently fails when keys expire. Non-owner cleanup unconditionally kills streams even when the worker holds the stream_manager. Fixes: - Use TSProxyServer.get_instance() in ProxyConfig.ready() - Remove flushdb() from Redis client initialization - Use sentinel pattern for gevent-safe singleton (threading.Lock does not work with gevent greenlets) - Single GET in get_channel_owner() to avoid TOCTOU race - Re-acquire expired ownership keys in extend_ownership() - Attempt re-acquisition before cleanup in non-owner path Relates to #992, #980
17 lines
649 B
Python
17 lines
649 B
Python
import sys
|
|
from django.apps import AppConfig
|
|
|
|
class ProxyConfig(AppConfig):
|
|
default_auto_field = 'django.db.models.BigAutoField'
|
|
name = 'apps.proxy'
|
|
verbose_name = "Stream Proxies"
|
|
|
|
def ready(self):
|
|
"""Initialize proxy servers when Django starts"""
|
|
if 'manage.py' not in sys.argv:
|
|
from .hls_proxy.server import ProxyServer as HLSProxyServer
|
|
from .ts_proxy.server import ProxyServer as TSProxyServer
|
|
|
|
# Initialize proxy servers (TS uses singleton to prevent duplicate instances)
|
|
self.hls_proxy = HLSProxyServer()
|
|
self.ts_proxy = TSProxyServer.get_instance()
|