From f373186dfd401c86df51d28d7b08837f772d5473 Mon Sep 17 00:00:00 2001 From: Jehan Date: Wed, 15 Jan 2025 18:35:27 +0100 Subject: [PATCH] app: fix a crash when closing an image. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A flush happens when closing image displays, and with the idle code, it means that the actual flush may happen once the image is already freed. When I was saying that multi-threading is always full of surprises… --- app/core/gimpprojection.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c index 5959bfd330..48ab93ed50 100644 --- a/app/core/gimpprojection.c +++ b/app/core/gimpprojection.c @@ -125,7 +125,7 @@ static void gimp_projection_add_update_area (GimpProjection *proj, gint w, gint h); static void gimp_projection_update_priority_rect (GimpProjection *proj); -static gboolean gimp_projection_chunk_render_start (GimpProjection *proj); +static gboolean gimp_projection_chunk_render_start (GWeakRef *proj_ref); static void gimp_projection_chunk_render_stop (GimpProjection *proj, gboolean merge); static gboolean gimp_projection_chunk_render_callback (GimpProjection *proj); @@ -502,12 +502,15 @@ gimp_projection_stop_rendering (GimpProjection *proj) void gimp_projection_flush (GimpProjection *proj) { + GWeakRef *proj_ref = g_new (GWeakRef, 1);; + g_return_if_fail (GIMP_IS_PROJECTION (proj)); + g_weak_ref_init (proj_ref, proj); /* Construct in chunks - asynchronously in the main thread */ g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc) gimp_projection_chunk_render_start, - proj, NULL); + proj_ref, NULL); } /** @@ -680,8 +683,17 @@ gimp_projection_update_priority_rect (GimpProjection *proj) } static gboolean -gimp_projection_chunk_render_start (GimpProjection *proj) +gimp_projection_chunk_render_start (GWeakRef *proj_ref) { + GimpProjection *proj; + + proj = g_weak_ref_get (proj_ref); + g_weak_ref_clear (proj_ref); + g_free (proj_ref); + + if (proj == NULL) + return G_SOURCE_REMOVE; + if (proj->priv->update_region) { cairo_region_t *region = proj->priv->update_region; @@ -754,6 +766,8 @@ gimp_projection_chunk_render_start (GimpProjection *proj) gimp_projectable_invalidate_preview (proj->priv->projectable); } + g_object_unref (proj); + return G_SOURCE_REMOVE; }