[gimp] app: in bucket-fill tool, cancel async on tool destruction



commit 663a6c701131c17e1222083560ed1b1102087e6b
Author: Ell <ell_se yahoo com>
Date:   Mon Nov 19 14:25:51 2018 -0500

    app: in bucket-fill tool, cancel async on tool destruction
    
    When computing line-art, don't ref the bucket-fill tool in the
    async data, and rather cancel any ongoing async upon tool
    destruction, so that the async callback doesn't attept to touch the
    now-dead tool.  This avoids segfaulting in the async callback when
    switching to a different tool, while a line-art async operation is
    active.
    
    Additionally, always cancel any previous async operation in
    gimp_bucket_fill_compute_line_art(), even if not starting a new
    one.

 app/tools/gimpbucketfilltool.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)
---
diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c
index dc3e18b020..9ce209c714 100644
--- a/app/tools/gimpbucketfilltool.c
+++ b/app/tools/gimpbucketfilltool.c
@@ -232,6 +232,17 @@ gimp_bucket_fill_tool_finalize (GObject *object)
   GimpImage             *image    = g_weak_ref_get (&tool->priv->cached_image);
   GimpDrawable          *drawable = g_weak_ref_get (&tool->priv->cached_drawable);
 
+  if (tool->priv->async)
+    {
+      /* we cancel the async, but don't wait for it to finish, since
+       * it can't actually be interrupted.  instead
+       * gimp_bucket_fill_compute_line_art_cb() bails if the async has
+       * been canceled, to avoid accessing the dead tool.
+       */
+      gimp_cancelable_cancel (GIMP_CANCELABLE (tool->priv->async));
+      g_clear_object (&tool->priv->async);
+    }
+
   g_clear_object (&tool->priv->line_art);
 
   if (image)
@@ -680,17 +691,15 @@ gimp_bucket_fill_tool_cursor_update (GimpTool         *tool,
 
 typedef struct
 {
-  GimpBucketFillTool *tool;
-  GimpPickable       *pickable;
-  gboolean            fill_transparent;
-  gdouble             line_art_threshold;
+  GimpPickable *pickable;
+  gboolean      fill_transparent;
+  gdouble       line_art_threshold;
 } PrecomputeData;
 
 static void
 precompute_data_free (PrecomputeData *data)
 {
   g_object_unref (data->pickable);
-  g_object_unref (data->tool);
   g_slice_free (PrecomputeData, data);
 }
 
@@ -731,6 +740,12 @@ gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool)
       return;
     }
 
+  if (tool->priv->async)
+    {
+      gimp_cancelable_cancel (GIMP_CANCELABLE (tool->priv->async));
+      g_clear_object (&tool->priv->async);
+    }
+
   g_clear_object (&tool->priv->line_art);
   if (options->fill_criterion == GIMP_SELECT_CRITERION_LINE_ART)
     {
@@ -758,16 +773,10 @@ gimp_bucket_fill_compute_line_art (GimpBucketFillTool *tool)
         {
           PrecomputeData *data = g_slice_new (PrecomputeData);
 
-          data->tool               = g_object_ref (tool);
           data->pickable           = pickable;
           data->fill_transparent   = options->fill_transparent;
           data->line_art_threshold = options->line_art_threshold;
 
-          if (tool->priv->async)
-            {
-              gimp_cancelable_cancel (GIMP_CANCELABLE (tool->priv->async));
-              g_object_unref (tool->priv->async);
-            }
           tool->priv->async = gimp_parallel_run_async_full (1,
                                                             (GimpParallelRunAsyncFunc) 
gimp_bucket_fill_compute_line_art_async,
                                                             data, (GDestroyNotify) precompute_data_free);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]