From ddbfe0fad6e43803e2c887a669012b7a83947dd2 Mon Sep 17 00:00:00 2001 From: Erich Seifert Date: Fri, 23 Oct 2026 04:10:28 +0200 Subject: [PATCH] Fix race on the cached image of the colour producer When the image had to be regenerated, the new buffer was stored on the producer and the lock released before the buffer was filled, and every frame copied the cached image without holding the lock. With frame threading, another thread could copy a partly filled image, or replace the cache for a different size or format and free the buffer that was being filled or copied. Keep the producer locked until the image is filled and copied. --- src/modules/core/producer_colour.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/modules/core/producer_colour.c b/src/modules/core/producer_colour.c index 450346f4e..2b1d7ff72 100644 --- a/src/modules/core/producer_colour.c +++ b/src/modules/core/producer_colour.c @@ -1,6 +1,6 @@ /* * producer_colour.c - * Copyright (C) 2003-2025 Meltytech, LLC + * Copyright (C) 2003-2026 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -130,8 +130,6 @@ static int producer_get_image(mlt_frame frame, mlt_properties_set_int(producer_props, "_format", *format); mlt_properties_set(producer_props, "_resource", now); - mlt_service_unlock(MLT_PRODUCER_SERVICE(producer)); - if (!strcmp(now, "checkerboard")) { struct mlt_image_s img; mlt_image_set_values(&img, NULL, *format, *width, *height); @@ -210,8 +208,6 @@ static int producer_get_image(mlt_frame frame, mlt_image_format_name(*format)); } } - } else { - mlt_service_unlock(MLT_PRODUCER_SERVICE(producer)); } // Create the alpha channel @@ -234,6 +230,9 @@ static int producer_get_image(mlt_frame frame, memcpy(*buffer, image, size); } + // The cached image may be replaced by another thread once unlocked + mlt_service_unlock(MLT_PRODUCER_SERVICE(producer)); + // Now update properties so we free the copy after mlt_frame_set_image(frame, *buffer, size, mlt_pool_release); mlt_frame_set_alpha(frame, alpha, alpha_size, mlt_pool_release);