PR #25663 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25663 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25663.patch
Fixes #25626. When `update_context_from_thread()` fails while submitting a drain packet, `submit_packet()` returns before the worker state and queue indices advance. Repeated `avcodec_receive_frame()` calls then retry the same context update indefinitely. Mark draining complete after reporting that error, and return EOF on subsequent calls. Tested on AArch64 with the issue’s 35-byte H.264 input. Before the patch, a two-second kill timeout returned 137 after 495,023 log lines. After the patch, `ffmpeg -err_detect explode -threads 2` exits with code 69 and eight log lines. The patched build also finishes with three threads and automatic thread selection. The corrupt input without `explode` and a separate H.264 sample finish. `git diff --check` passes. The unpatched release/9.0, release/8.1, release/8.0, and release/7.1 heads all reproduce the hang. From a42fdc78631ae9652ebcfe99fc4f4743d637a8da Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sun, 1 Nov 2026 20:17:44 +0000 Subject: [PATCH] avcodec/pthread_frame: stop draining after thread context update failure A failed update_thread_context() leaves the worker indices unchanged. During draining, repeated receive_frame() calls then retry the same empty packet indefinitely. Mark draining complete after reporting the error once, and return EOF on subsequent calls. Assisted-by: Fairy --- libavcodec/pthread_frame.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 8e88dda2ce0..5b1d1f58f6a 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -529,6 +529,10 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, (codec->capabilities & AV_CODEC_CAP_DELAY)) { ret = update_context_from_thread(p->avctx, prev_thread->avctx, 0); if (ret) { + /* No packet was submitted and the thread indices did not advance, + * so retrying the drain packet can repeat this error forever. */ + if (user_avctx->internal->draining) + user_avctx->internal->draining_done = 1; pthread_mutex_unlock(&p->mutex); return ret; } @@ -562,6 +566,11 @@ int ff_thread_receive_frame(AVCodecContext *avctx, AVFrame *frame, unsigned flag * go forward while we are in this function */ async_unlock(fctx); + if (avctx->internal->draining_done) { + ret = AVERROR_EOF; + goto finish; + } + /* submit packets to threads while there are no buffered results to return */ while (!fctx->df.nb_f && !fctx->result) { PerThreadContext *p; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
