From 0a619b14fa4f4d43ce0ab7dfcf89accbc06f2643 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 1 Feb 2016 15:37:57 -0500 Subject: Fix leak in wayland https://bugzilla.gnome.org/show_bug.cgi?id=761312 --- fix-leak.patch | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gtk3.spec | 8 ++- 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 fix-leak.patch diff --git a/fix-leak.patch b/fix-leak.patch new file mode 100644 index 0000000..be499df --- /dev/null +++ b/fix-leak.patch @@ -0,0 +1,159 @@ +From 4bb5bc005f8ffea31fa104a7238b855c7c20cba6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 29 Jan 2016 11:19:03 -0500 +Subject: [PATCH] wayland: Don't call set_busy twice on the same surface + +If the compositor is using a shared memory buffer allocated by +a client, then it's the client's responsibility to refrain from +destroying the buffer until the compositor releases it. + +This is accomplished by taking a reference to the cairo surface +assocatiated with the buffer after a frame, and dropping the +reference when the compositor releases the buffer. + +In some cases though, the compositor doesn't release the buffer +until a new buffer is set, so if we have staged drawing before +the frame completes we can end up taking multiple references to +the buffer and keeping it alive after it's released. + +This commit solves the problem by ensuring we only call +_gdk_wayland_shm_surface_set_busy if isn't already busy. + +https://bugzilla.gnome.org/show_bug.cgi?id=761312 +--- + gdk/wayland/gdkdisplay-wayland.c | 3 +++ + gdk/wayland/gdkwindow-wayland.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index f200800..a589756 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -1020,54 +1020,57 @@ _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display, + width*scale, height*scale, + stride, WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener (data->buffer, &buffer_listener, surface); + + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key, + data, gdk_wayland_cairo_surface_destroy); + + cairo_surface_set_device_scale (surface, scale, scale); + + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) + { + g_critical (G_STRLOC ": Unable to create Cairo image surface: %s", + cairo_status_to_string (status)); + } + + return surface; + } + + struct wl_buffer * + _gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface) + { + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + return data->buffer; + } + + void + _gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface) + { + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); ++ ++ g_assert (!data->busy); ++ + data->busy = TRUE; + cairo_surface_reference (surface); + } + + gboolean + _gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface) + { + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + return data->busy; + } + + gboolean + _gdk_wayland_is_shm_surface (cairo_surface_t *surface) + { + return cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key) != NULL; + } + + GdkWaylandSelection * + gdk_wayland_display_get_selection (GdkDisplay *display) + { + GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display); + + return wayland_display->selection; + } +diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c +index 8e74ef4..6dac820 100644 +--- a/gdk/wayland/gdkwindow-wayland.c ++++ b/gdk/wayland/gdkwindow-wayland.c +@@ -420,61 +420,61 @@ on_frame_clock_before_paint (GdkFrameClock *clock, + timings->predicted_presentation_time = presentation_time + refresh_interval; + } + else + { + /* As above, but we don't actually know the phase of the vblank, + * so just assume that we're half way through a refresh cycle. + */ + timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval; + } + } + + static void + on_frame_clock_after_paint (GdkFrameClock *clock, + GdkWindow *window) + { + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + struct wl_callback *callback; + + if (!impl->pending_commit) + return; + + impl->pending_commit = FALSE; + impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock); + impl->awaiting_frame = TRUE; + + callback = wl_surface_frame (impl->surface); + wl_callback_add_listener (callback, &frame_listener, window); + _gdk_frame_clock_freeze (clock); + + wl_surface_commit (impl->surface); +- if (_gdk_wayland_is_shm_surface (impl->cairo_surface)) ++ if (_gdk_wayland_is_shm_surface (impl->cairo_surface) && !_gdk_wayland_shm_surface_get_busy (impl->cairo_surface)) + _gdk_wayland_shm_surface_set_busy (impl->cairo_surface); + + g_signal_emit (impl, signals[COMMITTED], 0); + } + + static void + window_update_scale (GdkWindow *window) + { + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); + guint32 scale; + GSList *l; + + if (wayland_display->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE) + { + /* We can't set the scale on this surface */ + return; + } + + scale = 1; + for (l = impl->outputs; l != NULL; l = l->next) + { + guint32 output_scale = + _gdk_wayland_screen_get_output_scale (wayland_display->screen, l->data); + scale = MAX (scale, output_scale); + } + + /* Notify app that scale changed */ + gdk_wayland_window_configure (window, window->width, window->height, scale); + } +-- +2.7.0 + diff --git a/gtk3.spec b/gtk3.spec index ccc0b17..1b6c1d5 100644 --- a/gtk3.spec +++ b/gtk3.spec @@ -18,13 +18,14 @@ Summary: The GIMP ToolKit (GTK+), a library for creating GUIs for X Name: gtk3 Version: 3.19.8 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.gtk.org #VCS: git:git://git.gnome.org/gtk+ Source: http://download.gnome.org/sources/gtk+/3.19/gtk+-%{version}.tar.xz +Patch0: fix-leak.patch BuildRequires: gnome-common autoconf automake intltool gettext BuildRequires: pkgconfig(atk) >= %{atk_version} @@ -167,6 +168,7 @@ the functionality of the installed %{name} package. %prep %setup -q -n gtk+-%{version} +%patch0 -p1 -b .fix-leak %build @@ -340,6 +342,10 @@ gtk-query-immodules-3.0-%{__isa_bits} --update-cache %{_datadir}/installed-tests %changelog +* Mon Feb 01 2016 Ray Strode - 3.19.8-2 +- Fix leak in wayland + https://bugzilla.gnome.org/show_bug.cgi?id=761312 + * Mon Feb 1 2016 Matthias Clasen - 3.19.8-1 - Update to 3.19.8 -- cgit