diff options
author | Pekka Vuorela <pvuorela@iki.fi> | 2012-09-17 22:15:57 +0300 |
---|---|---|
committer | Tiago Vignatti <tiago.vignatti@intel.com> | 2012-09-26 17:38:41 +0300 |
commit | b0b3c6f16d5884e9eecfbad39526b8b29be24b18 (patch) | |
tree | f5c0c455c89c416771a1121ad6246626d56b03d0 | |
parent | 5eca7ed3a1b0b62b2f43629c0f37d28a04ac15a3 (diff) |
Protect window callbacks from deleted windows
Calling window_destroy() was able to cause segfault for
callbacks triggering afterwards.
-rw-r--r-- | clients/window.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/clients/window.c b/clients/window.c index c784911..93d2282 100644 --- a/clients/window.c +++ b/clients/window.c @@ -166,6 +166,8 @@ struct window { window_close_handler_t close_handler; window_fullscreen_handler_t fullscreen_handler; + struct wl_callback *frame_cb; + struct frame *frame; struct widget *widget; @@ -993,6 +995,8 @@ window_destroy(struct window *window) if (window->cairo_surface != NULL) cairo_surface_destroy(window->cairo_surface); + if (window->frame_cb) + wl_callback_destroy(window->frame_cb); free(window->title); free(window); } @@ -2004,6 +2008,9 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer, input->sx = sx; input->sy = sy; + if (!window) + return; + if (!(input->grab && input->grab_button)) { widget = widget_find_widget(window->widget, sx, sy); input_set_focus_widget(input, widget, sx, sy); @@ -2875,7 +2882,9 @@ frame_callback(void *data, struct wl_callback *callback, uint32_t time) { struct window *window = data; + assert(callback == window->frame_cb); wl_callback_destroy(callback); + window->frame_cb = 0; window->redraw_scheduled = 0; if (window->redraw_needed) window_schedule_redraw(window); @@ -2889,7 +2898,6 @@ static void idle_redraw(struct task *task, uint32_t events) { struct window *window = container_of(task, struct window, redraw_task); - struct wl_callback *callback; if (window->resize_needed) idle_resize(window); @@ -2900,8 +2908,8 @@ idle_redraw(struct task *task, uint32_t events) window->redraw_needed = 0; wl_list_init(&window->redraw_task.link); - callback = wl_surface_frame(window->surface); - wl_callback_add_listener(callback, &listener, window); + window->frame_cb = wl_surface_frame(window->surface); + wl_callback_add_listener(window->frame_cb, &listener, window); } void |