aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWizardOfYendor1 <WizardOfYendor1@users.noreply.github.com>2026-02-28 11:21:53 -0500
committerWizardOfYendor1 <WizardOfYendor1@users.noreply.github.com>2026-03-27 20:11:26 -0400
commit3a4dff8cc475e53691466dde2db9828b4d1b66aa (patch)
treed2c182893452335d7a0574c427ffc410e2e61ea2
parente807575dc7b3d2eebbbe1a2bab197c07f84f6508 (diff)
Fix live stream consumer leak when PositionTicks is negative
When a stalled HLS client sends ReportPlaybackStopped with a negative PositionTicks (e.g. HLS.js reporting position on buffer stall), the ArgumentOutOfRangeException was thrown before GetSession was called, causing CloseLiveStreamIfNeededAsync to never run. This left the ILiveStream.ConsumerCount permanently incremented, permanently holding a tuner open with no active viewer. Fix by acquiring the session and performing live stream cleanup before throwing the validation exception, so tuner resources are always freed even when playback reporting fails with invalid position data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs15
1 files changed, 11 insertions, 4 deletions
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 8e14f5bdf4..7e13e17eb6 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1025,15 +1025,22 @@ namespace Emby.Server.Implementations.Session
ArgumentNullException.ThrowIfNull(info);
+ var session = GetSession(info.SessionId);
+
+ session.StopAutomaticProgress();
+
if (info.PositionTicks.HasValue && info.PositionTicks.Value < 0)
{
+ // Ensure live stream is cleaned up before throwing, to prevent tuner
+ // resource leaks when stalled clients report a negative PositionTicks.
+ if (!string.IsNullOrEmpty(info.LiveStreamId))
+ {
+ await CloseLiveStreamIfNeededAsync(info.LiveStreamId, session.Id).ConfigureAwait(false);
+ }
+
throw new ArgumentOutOfRangeException(nameof(info), "The PlaybackStopInfo's PositionTicks was negative.");
}
- var session = GetSession(info.SessionId);
-
- session.StopAutomaticProgress();
-
var libraryItem = info.ItemId.IsEmpty()
? null
: GetNowPlayingItem(session, info.ItemId);