From 2b87bb015cd057ea44f8d9767386f6437848ed71 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 25 Mar 2012 11:54:08 -0300 Subject: [PATCH] screenshot: Ensure that ShellScreenshot stays alive until the callback We've been dangling on the edge of unsafety, unnoticed, for a little while about the reference count safety of ShellScreenshot. GJS owns the entire reference count, so as soon as it goes out of scope it could die, causing GJS to try and fetch the corresponding wrapper object for a stale pointer. We haven't seen any crashes because of luck -- SpiderMonkey tries to group together deallocations to limit GC pauses, and there isn't really a lot of GC pressure in the duration that a screenshot happens, so we tend to be mostly stable. But in the case that you create a lot of objects while a screenshot is going on, by hammering the "Print Screen" button, for example, you can destroy the GObject before the callback finishes. https://bugzilla.gnome.org/show_bug.cgi?id=672775 --- src/shell-screenshot.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c index b0dcfa38c..33b981e8e 100644 --- a/src/shell-screenshot.c +++ b/src/shell-screenshot.c @@ -65,6 +65,7 @@ on_screenshot_written (GObject *source, &screenshot_data->screenshot_area); cairo_surface_destroy (screenshot_data->image); + g_object_unref (screenshot_data->screenshot); g_free (screenshot_data->filename); g_free (screenshot_data); } @@ -262,7 +263,7 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot, ClutterActor *stage; _screenshot_data *data = g_new0 (_screenshot_data, 1); - data->screenshot = screenshot; + data->screenshot = g_object_ref (screenshot); data->filename = g_strdup (filename); data->callback = callback; data->include_cursor = include_cursor; @@ -301,7 +302,7 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot, ClutterActor *stage; _screenshot_data *data = g_new0 (_screenshot_data, 1); - data->screenshot = screenshot; + data->screenshot = g_object_ref (screenshot); data->filename = g_strdup (filename); data->screenshot_area.x = x; data->screenshot_area.y = y; @@ -350,7 +351,7 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot, MetaRectangle rect; cairo_rectangle_int_t clip; - screenshot_data->screenshot = screenshot; + screenshot_data->screenshot = g_object_ref (screenshot); screenshot_data->filename = g_strdup (filename); screenshot_data->callback = callback;