From e2586eed9b04d501cd5805711cb6ad5553c1816b Mon Sep 17 00:00:00 2001 From: gnattu Date: Wed, 5 Aug 2026 00:33:42 +0800 Subject: Fix concurrent ffmpeg segment racing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a nasty one. The failure mode is: 1. Request A started FFmpeg and waited for a segment. 2. Request B requested an earlier or far away segment. 3. Jellyfin thought FFmpeg should to restart at a different position. 4. Request B killed the existing transcoding job. 5. Killing that job cancelled the same token request A was using. 6. The cancellation produced http 500 to request A. To fix this: we lock transcoding job state changes and segment handling per playlist, and use a thread safe counter to track how many http responses are still using each job’s segments. A job is only stopped or replaced once that counter reaches zero. --- MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs') diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs index 78bb881ec2..dfc057f611 100644 --- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs +++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs @@ -612,9 +612,9 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable /// public void OnTranscodeEndRequest(TranscodingJob job) { - job.ActiveRequestCount--; - _logger.LogDebug("OnTranscodeEndRequest job.ActiveRequestCount={ActiveRequestCount}", job.ActiveRequestCount); - if (job.ActiveRequestCount <= 0) + var activeRequestCount = job.DecrementActiveRequestCount(); + _logger.LogDebug("OnTranscodeEndRequest job.ActiveRequestCount={ActiveRequestCount}", activeRequestCount); + if (activeRequestCount <= 0) { PingTimer(job, false); } @@ -697,7 +697,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable return null; } - job.ActiveRequestCount++; + job.IncrementActiveRequestCount(); if (string.IsNullOrWhiteSpace(job.PlaySessionId) || job.Type == TranscodingJobType.Progressive) { job.StopKillTimer(); -- cgit v1.2.3