xwm: Fix memory leak
A memory leak introduced by 6b58ea8c led to me finding a bigger leak,
which is xwm was calling frame_create() without calling frame_destroy().
This meant that the associated icon_surface was not being destroyed,
leaving the destroy handler for it broken. Here we fix this by calling
frame_destroy() when the window is destroyed and free the reply in
the icon_surface destroy handler.
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
committed by
Derek Foreman
parent
9fe5d5fae9
commit
4d1cd36c9e
@@ -1352,6 +1352,12 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window)
|
|||||||
weston_wm_window_do_repaint, window);
|
weston_wm_window_do_repaint, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_icon_surface_destroy(void *data)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
|
weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
|
||||||
{
|
{
|
||||||
@@ -1371,16 +1377,20 @@ weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
|
|||||||
length = xcb_get_property_value_length(reply);
|
length = xcb_get_property_value_length(reply);
|
||||||
|
|
||||||
/* This is in 32-bit words, not in bytes. */
|
/* This is in 32-bit words, not in bytes. */
|
||||||
if (length < 2)
|
if (length < 2) {
|
||||||
|
free(reply);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data = xcb_get_property_value(reply);
|
data = xcb_get_property_value(reply);
|
||||||
width = *data++;
|
width = *data++;
|
||||||
height = *data++;
|
height = *data++;
|
||||||
|
|
||||||
/* Some checks against malformed input. */
|
/* Some checks against malformed input. */
|
||||||
if (width == 0 || height == 0 || length < 2 + width * height)
|
if (width == 0 || height == 0 || length < 2 + width * height) {
|
||||||
|
free(reply);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
new_surface =
|
new_surface =
|
||||||
cairo_image_surface_create_for_data((unsigned char *)data,
|
cairo_image_surface_create_for_data((unsigned char *)data,
|
||||||
@@ -1390,9 +1400,13 @@ weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
|
|||||||
/* Bail out in case anything wrong happened during surface creation. */
|
/* Bail out in case anything wrong happened during surface creation. */
|
||||||
if (cairo_surface_status(new_surface) != CAIRO_STATUS_SUCCESS) {
|
if (cairo_surface_status(new_surface) != CAIRO_STATUS_SUCCESS) {
|
||||||
cairo_surface_destroy(new_surface);
|
cairo_surface_destroy(new_surface);
|
||||||
|
free(reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cairo_surface_set_user_data(new_surface, NULL, reply,
|
||||||
|
&handle_icon_surface_destroy);
|
||||||
|
|
||||||
if (window->frame)
|
if (window->frame)
|
||||||
frame_set_icon(window->frame, new_surface);
|
frame_set_icon(window->frame, new_surface);
|
||||||
else /* We don’t have a frame yet */
|
else /* We don’t have a frame yet */
|
||||||
@@ -1502,6 +1516,9 @@ weston_wm_window_destroy(struct weston_wm_window *window)
|
|||||||
window->frame_id = XCB_WINDOW_NONE;
|
window->frame_id = XCB_WINDOW_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
frame_destroy(window->frame);
|
||||||
|
|
||||||
if (window->surface_id)
|
if (window->surface_id)
|
||||||
wl_list_remove(&window->link);
|
wl_list_remove(&window->link);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user