clients/window: Defer closing of window

Instead of closing the window directly by calling close_handler() use a
deferred task to do that instead.

That way we avoid a potential invalid access on a link which was
previously removed, due to the fact both window_destroy() and
touch_handle_up() traverse the same list.

This is an alternative to 841.

Fixes: #607.

Suggested-by: Pekka Paalanen <pekka.paalanen@collabora.com>
Reported-by: He Yong <hyyoxhk@163.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
dev
Marius Vlad 2 years ago
parent 57d32722a2
commit cc69dc447e
  1. 17
      clients/window.c

@ -240,6 +240,7 @@ struct window {
int redraw_needed; int redraw_needed;
int redraw_task_scheduled; int redraw_task_scheduled;
struct task redraw_task; struct task redraw_task;
struct task close_task;
int resize_needed; int resize_needed;
int custom; int custom;
int focused; int focused;
@ -1429,14 +1430,24 @@ window_has_focus(struct window *window)
return window->focused; return window->focused;
} }
static void static void
window_close(struct window *window) close_task_run(struct task *task, uint32_t events)
{ {
if (window->close_handler) struct window *window = container_of(task, struct window, close_task);
window->close_handler(window->user_data); window->close_handler(window->user_data);
else }
static void
window_close(struct window *window)
{
if (window->close_handler && !window->close_task.run) {
window->close_task.run = close_task_run;
display_defer(window->display, &window->close_task);
} else {
display_exit(window->display); display_exit(window->display);
} }
}
struct display * struct display *
window_get_display(struct window *window) window_get_display(struct window *window)

Loading…
Cancel
Save