Issue #11922: Fatal error on closing main window when in export plug-in.

This commit is contained in:
Jehan 2024-08-30 16:32:45 +02:00
parent 8b57aabed2
commit 42f7a167c3
3 changed files with 78 additions and 49 deletions

View File

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

View File

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

View File

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