From 34093ca43d215732e5eac3d0bf3b061b7f65aa84 Mon Sep 17 00:00:00 2001 From: Dmitry Guryanov Date: Tue, 17 Jul 2012 16:51:15 +0400 Subject: [PATCH] remove listener from wl_data_source destroy_signal listener list In function drag_grab_button we first call data_device_end_drag_grab, which sets seat->drag_data_source to NULL. Then we remove listener from list only if drag_data_source is not NULL. So if client will not free wl_data_source and start another drag'n'drop, after the first one. Then two wl_data_source structures will be free'd on client exit (let's name them s1 and s2). next and prev pointer of wl_data_source.resource.destroy_signal.listener_list in both wl_data_source structures will be seat->drag_data_source_listener, but next and prev in seat->drag_data_source_listener.link point to listener_list in s2. So if you try to iterate over listener_list in s1 then you get drag_data_source_listener as first item and (struct wl_listener *)(&s2.resource.destroy_signal.listener_list) Iteration over that list occurs in wl_resource_destroy->destroy_resource->wl_signal_emit->wl_signal_emit and try to call function at address of wl_resource->client, so weston segfaults there. --- src/data-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data-device.c b/src/data-device.c index 67ae41f..82020af 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -265,9 +265,9 @@ drag_grab_button(struct wl_pointer_grab *grab, if (seat->pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED) { - data_device_end_drag_grab(seat); if (seat->drag_data_source) wl_list_remove(&seat->drag_data_source_listener.link); + data_device_end_drag_grab(seat); } } -- 1.7.10.4