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.
This commit is contained in:
Ell 2018-11-19 14:25:51 -05:00
parent 62baffed98
commit 663a6c7011
1 changed files with 20 additions and 11 deletions

View File

@ -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);