diff --git a/app/core/gimp.c b/app/core/gimp.c index 1040670d0e..95e46174cb 100644 --- a/app/core/gimp.c +++ b/app/core/gimp.c @@ -103,34 +103,36 @@ enum }; -static void gimp_constructed (GObject *object); -static void gimp_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); -static void gimp_dispose (GObject *object); -static void gimp_finalize (GObject *object); +static void gimp_constructed (GObject *object); +static void gimp_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_dispose (GObject *object); +static void gimp_finalize (GObject *object); -static gint64 gimp_get_memsize (GimpObject *object, - gint64 *gui_size); +static gint64 gimp_get_memsize (GimpObject *object, + gint64 *gui_size); -static void gimp_real_initialize (Gimp *gimp, - GimpInitStatusFunc status_callback); -static void gimp_real_restore (Gimp *gimp, - GimpInitStatusFunc status_callback); -static gboolean gimp_real_exit (Gimp *gimp, - gboolean force); +static void gimp_real_initialize (Gimp *gimp, + GimpInitStatusFunc status_callback); +static void gimp_real_restore (Gimp *gimp, + GimpInitStatusFunc status_callback); +static gboolean gimp_real_exit (Gimp *gimp, + gboolean force); -static void gimp_global_config_notify (GObject *global_config, - GParamSpec *param_spec, - GObject *edit_config); -static void gimp_edit_config_notify (GObject *edit_config, - GParamSpec *param_spec, - GObject *global_config); +static void gimp_global_config_notify (GObject *global_config, + GParamSpec *param_spec, + GObject *edit_config); +static void gimp_edit_config_notify (GObject *edit_config, + GParamSpec *param_spec, + GObject *global_config); + +static gboolean gimp_exit_idle_cleanup_stray_images (Gimp *gimp); G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT) @@ -891,8 +893,7 @@ void gimp_exit (Gimp *gimp, gboolean force) { - gboolean handled; - GList *image_iter; + gboolean handled; g_return_if_fail (GIMP_IS_GIMP (gimp)); @@ -906,17 +907,9 @@ gimp_exit (Gimp *gimp, if (handled) return; - /* Get rid of images without display. We do this *after* handling the - * usual exit callbacks, because the things that are torn down there - * might have references to these images (for instance GimpActions - * in the UI manager). - */ - while ((image_iter = gimp_get_image_iter (gimp))) - { - GimpImage *image = image_iter->data; - - g_object_unref (image); - } + g_idle_add_full (G_PRIORITY_LOW, + (GSourceFunc) gimp_exit_idle_cleanup_stray_images, + gimp, NULL); } GList * @@ -1237,3 +1230,27 @@ gimp_get_temp_file (Gimp *gimp, return file; } + +static gboolean +gimp_exit_idle_cleanup_stray_images (Gimp *gimp) +{ + GList *image_iter; + + while (g_main_context_pending (NULL)) + g_main_context_iteration (NULL, TRUE); + + /* Get rid of images without display. We do this *after* handling the + * usual exit callbacks and any other pending event, because the + * things that are torn down there might have references to these + * images, for instance GimpActions in the UI manager, or some plug-in + * which was still running and had to get killed in gimp_exit() (cf. #11922). + */ + while ((image_iter = gimp_get_image_iter (gimp))) + { + GimpImage *image = image_iter->data; + + g_object_unref (image); + } + + return G_SOURCE_REMOVE ; +} diff --git a/app/dialogs/file-save-dialog.c b/app/dialogs/file-save-dialog.c index 0f5acfa779..27ed3b654d 100644 --- a/app/dialogs/file-save-dialog.c +++ b/app/dialogs/file-save-dialog.c @@ -820,6 +820,13 @@ file_save_dialog_save_image (GimpProgress *progress, gimp_image_set_xcf_compression (image, xcf_compression); + /* The save may fail and the progress widget be already freed if we + * close the main window while the save dialog is running. So add a + * weak pointer to avoid sending an error message to an already-freed + * GimpProgress. See #11922. + */ + g_object_add_weak_pointer (G_OBJECT (progress), (gpointer *) &progress); + status = file_save (gimp, image, progress, file, save_proc, run_mode, change_saved_state, export_backward, export_forward, @@ -832,7 +839,7 @@ file_save_dialog_save_image (GimpProgress *progress, break; case GIMP_PDB_CANCEL: - if (verbose_cancel) + if (verbose_cancel && progress) gimp_message_literal (gimp, G_OBJECT (progress), GIMP_MESSAGE_INFO, _("Saving canceled")); @@ -840,15 +847,19 @@ file_save_dialog_save_image (GimpProgress *progress, default: { - gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, - _("Saving '%s' failed:\n\n%s"), - gimp_file_get_utf8_name (file), - error ? error->message : _("Unknown error")); + if (progress) + gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, + _("Saving '%s' failed:\n\n%s"), + gimp_file_get_utf8_name (file), + error ? error->message : _("Unknown error")); g_clear_error (&error); } break; } + if (progress) + g_object_remove_weak_pointer (G_OBJECT (progress), (gpointer *) &progress); + for (list = gimp_action_groups_from_name ("file"); list; list = g_list_next (list)) diff --git a/app/plug-in/gimpplugin.c b/app/plug-in/gimpplugin.c index 7d02359052..b4e66c0795 100644 --- a/app/plug-in/gimpplugin.c +++ b/app/plug-in/gimpplugin.c @@ -770,7 +770,7 @@ gimp_plug_in_close (GimpPlugIn *plug_in, { GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data; -#ifdef GIMP_UNSTABLE +#ifndef GIMP_RELEASE g_printerr ("plug-in '%s' aborted before sending its " "temporary procedure return values\n", gimp_object_get_name (plug_in)); @@ -792,10 +792,11 @@ gimp_plug_in_close (GimpPlugIn *plug_in, if (plug_in->main_proc_frame.main_loop && g_main_loop_is_running (plug_in->main_proc_frame.main_loop)) { -#ifdef GIMP_UNSTABLE - g_printerr ("plug-in '%s' aborted before sending its " - "procedure return values\n", - gimp_object_get_name (plug_in)); +#ifndef GIMP_RELEASE + if (! kill_it) + g_printerr ("plug-in '%s' aborted before sending its " + "procedure return values\n", + gimp_object_get_name (plug_in)); #endif g_main_loop_quit (plug_in->main_proc_frame.main_loop); @@ -804,7 +805,7 @@ gimp_plug_in_close (GimpPlugIn *plug_in, if (plug_in->ext_main_loop && g_main_loop_is_running (plug_in->ext_main_loop)) { -#ifdef GIMP_UNSTABLE +#ifndef GIMP_RELEASE g_printerr ("extension '%s' aborted before sending its " "extension_ack message\n", gimp_object_get_name (plug_in));