Issue #11922: Fatal error on closing main window when in export plug-in.
This commit is contained in:
@ -103,34 +103,36 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void gimp_constructed (GObject *object);
|
static void gimp_constructed (GObject *object);
|
||||||
static void gimp_set_property (GObject *object,
|
static void gimp_set_property (GObject *object,
|
||||||
guint property_id,
|
guint property_id,
|
||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
static void gimp_get_property (GObject *object,
|
static void gimp_get_property (GObject *object,
|
||||||
guint property_id,
|
guint property_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
static void gimp_dispose (GObject *object);
|
static void gimp_dispose (GObject *object);
|
||||||
static void gimp_finalize (GObject *object);
|
static void gimp_finalize (GObject *object);
|
||||||
|
|
||||||
static gint64 gimp_get_memsize (GimpObject *object,
|
static gint64 gimp_get_memsize (GimpObject *object,
|
||||||
gint64 *gui_size);
|
gint64 *gui_size);
|
||||||
|
|
||||||
static void gimp_real_initialize (Gimp *gimp,
|
static void gimp_real_initialize (Gimp *gimp,
|
||||||
GimpInitStatusFunc status_callback);
|
GimpInitStatusFunc status_callback);
|
||||||
static void gimp_real_restore (Gimp *gimp,
|
static void gimp_real_restore (Gimp *gimp,
|
||||||
GimpInitStatusFunc status_callback);
|
GimpInitStatusFunc status_callback);
|
||||||
static gboolean gimp_real_exit (Gimp *gimp,
|
static gboolean gimp_real_exit (Gimp *gimp,
|
||||||
gboolean force);
|
gboolean force);
|
||||||
|
|
||||||
static void gimp_global_config_notify (GObject *global_config,
|
static void gimp_global_config_notify (GObject *global_config,
|
||||||
GParamSpec *param_spec,
|
GParamSpec *param_spec,
|
||||||
GObject *edit_config);
|
GObject *edit_config);
|
||||||
static void gimp_edit_config_notify (GObject *edit_config,
|
static void gimp_edit_config_notify (GObject *edit_config,
|
||||||
GParamSpec *param_spec,
|
GParamSpec *param_spec,
|
||||||
GObject *global_config);
|
GObject *global_config);
|
||||||
|
|
||||||
|
static gboolean gimp_exit_idle_cleanup_stray_images (Gimp *gimp);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT)
|
G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT)
|
||||||
@ -891,8 +893,7 @@ void
|
|||||||
gimp_exit (Gimp *gimp,
|
gimp_exit (Gimp *gimp,
|
||||||
gboolean force)
|
gboolean force)
|
||||||
{
|
{
|
||||||
gboolean handled;
|
gboolean handled;
|
||||||
GList *image_iter;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||||
|
|
||||||
@ -906,17 +907,9 @@ gimp_exit (Gimp *gimp,
|
|||||||
if (handled)
|
if (handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Get rid of images without display. We do this *after* handling the
|
g_idle_add_full (G_PRIORITY_LOW,
|
||||||
* usual exit callbacks, because the things that are torn down there
|
(GSourceFunc) gimp_exit_idle_cleanup_stray_images,
|
||||||
* might have references to these images (for instance GimpActions
|
gimp, NULL);
|
||||||
* in the UI manager).
|
|
||||||
*/
|
|
||||||
while ((image_iter = gimp_get_image_iter (gimp)))
|
|
||||||
{
|
|
||||||
GimpImage *image = image_iter->data;
|
|
||||||
|
|
||||||
g_object_unref (image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *
|
GList *
|
||||||
@ -1237,3 +1230,27 @@ gimp_get_temp_file (Gimp *gimp,
|
|||||||
|
|
||||||
return file;
|
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 ;
|
||||||
|
}
|
||||||
|
@ -820,6 +820,13 @@ file_save_dialog_save_image (GimpProgress *progress,
|
|||||||
|
|
||||||
gimp_image_set_xcf_compression (image, xcf_compression);
|
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,
|
status = file_save (gimp, image, progress, file,
|
||||||
save_proc, run_mode,
|
save_proc, run_mode,
|
||||||
change_saved_state, export_backward, export_forward,
|
change_saved_state, export_backward, export_forward,
|
||||||
@ -832,7 +839,7 @@ file_save_dialog_save_image (GimpProgress *progress,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_PDB_CANCEL:
|
case GIMP_PDB_CANCEL:
|
||||||
if (verbose_cancel)
|
if (verbose_cancel && progress)
|
||||||
gimp_message_literal (gimp,
|
gimp_message_literal (gimp,
|
||||||
G_OBJECT (progress), GIMP_MESSAGE_INFO,
|
G_OBJECT (progress), GIMP_MESSAGE_INFO,
|
||||||
_("Saving canceled"));
|
_("Saving canceled"));
|
||||||
@ -840,15 +847,19 @@ file_save_dialog_save_image (GimpProgress *progress,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR,
|
if (progress)
|
||||||
_("Saving '%s' failed:\n\n%s"),
|
gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR,
|
||||||
gimp_file_get_utf8_name (file),
|
_("Saving '%s' failed:\n\n%s"),
|
||||||
error ? error->message : _("Unknown error"));
|
gimp_file_get_utf8_name (file),
|
||||||
|
error ? error->message : _("Unknown error"));
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (progress)
|
||||||
|
g_object_remove_weak_pointer (G_OBJECT (progress), (gpointer *) &progress);
|
||||||
|
|
||||||
for (list = gimp_action_groups_from_name ("file");
|
for (list = gimp_action_groups_from_name ("file");
|
||||||
list;
|
list;
|
||||||
list = g_list_next (list))
|
list = g_list_next (list))
|
||||||
|
@ -770,7 +770,7 @@ gimp_plug_in_close (GimpPlugIn *plug_in,
|
|||||||
{
|
{
|
||||||
GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
|
GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
|
||||||
|
|
||||||
#ifdef GIMP_UNSTABLE
|
#ifndef GIMP_RELEASE
|
||||||
g_printerr ("plug-in '%s' aborted before sending its "
|
g_printerr ("plug-in '%s' aborted before sending its "
|
||||||
"temporary procedure return values\n",
|
"temporary procedure return values\n",
|
||||||
gimp_object_get_name (plug_in));
|
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 &&
|
if (plug_in->main_proc_frame.main_loop &&
|
||||||
g_main_loop_is_running (plug_in->main_proc_frame.main_loop))
|
g_main_loop_is_running (plug_in->main_proc_frame.main_loop))
|
||||||
{
|
{
|
||||||
#ifdef GIMP_UNSTABLE
|
#ifndef GIMP_RELEASE
|
||||||
g_printerr ("plug-in '%s' aborted before sending its "
|
if (! kill_it)
|
||||||
"procedure return values\n",
|
g_printerr ("plug-in '%s' aborted before sending its "
|
||||||
gimp_object_get_name (plug_in));
|
"procedure return values\n",
|
||||||
|
gimp_object_get_name (plug_in));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_main_loop_quit (plug_in->main_proc_frame.main_loop);
|
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 &&
|
if (plug_in->ext_main_loop &&
|
||||||
g_main_loop_is_running (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 "
|
g_printerr ("extension '%s' aborted before sending its "
|
||||||
"extension_ack message\n",
|
"extension_ack message\n",
|
||||||
gimp_object_get_name (plug_in));
|
gimp_object_get_name (plug_in));
|
||||||
|
Reference in New Issue
Block a user