From 44874d9f022de21dbd2c8aa3cf9c9bb5a0506f68 Mon Sep 17 00:00:00 2001 From: "U. Artie Eoff" Date: Tue, 2 Oct 2012 21:12:35 -0700 Subject: [PATCH] desktop-shell: destroy data before exiting. desktop-shell never returned from display_run() since it was essentially killed when weston exited. To fix this, it is necessary to watch for EPOLLHUP in window.c so that toytoolkit clients will return from display_run() when weston quits. This allows for clients to clean up as needed. Signed-off-by: U. Artie Eoff --- clients/desktop-shell.c | 88 +++++++++++++++++++++++++++++++++++++++++ clients/window.c | 21 ++++++++-- 2 files changed, 105 insertions(+), 4 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 588dc1cd..dc436525 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -371,6 +371,16 @@ clock_timer_reset(struct panel_clock *clock) return 0; } +static void +panel_destroy_clock(struct panel_clock *clock) +{ + widget_destroy(clock->widget); + + close(clock->clock_fd); + + free(clock); +} + static void panel_add_clock(struct panel *panel) { @@ -447,6 +457,39 @@ panel_configure(void *data, window_schedule_resize(panel->window, width, 32); } +static void +panel_destroy_launcher(struct panel_launcher *launcher) +{ + wl_array_release(&launcher->argv); + wl_array_release(&launcher->envp); + + free(launcher->path); + + cairo_surface_destroy(launcher->icon); + + widget_destroy(launcher->widget); + wl_list_remove(&launcher->link); + + free(launcher); +} + +static void +panel_destroy(struct panel *panel) +{ + struct panel_launcher *tmp; + struct panel_launcher *launcher; + + panel_destroy_clock(panel->clock); + + wl_list_for_each_safe(launcher, tmp, &panel->launcher_list, link) + panel_destroy_launcher(launcher); + + widget_destroy(panel->widget); + window_destroy(panel->window); + + free(panel); +} + static struct panel * panel_create(struct display *display) { @@ -885,6 +928,15 @@ static const struct desktop_shell_listener listener = { desktop_shell_grab_cursor }; +static void +background_destroy(struct background *background) +{ + widget_destroy(background->widget); + window_destroy(background->window); + + free(background); +} + static struct background * background_create(struct desktop *desktop) { @@ -911,6 +963,13 @@ grab_surface_enter_handler(struct widget *widget, struct input *input, return desktop->grab_cursor; } +static void +grab_surface_destroy(struct desktop *desktop) +{ + widget_destroy(desktop->grab_widget); + window_destroy(desktop->grab_window); +} + static void grab_surface_create(struct desktop *desktop) { @@ -932,6 +991,27 @@ grab_surface_create(struct desktop *desktop) grab_surface_enter_handler); } +static void +output_destroy(struct output *output) +{ + background_destroy(output->background); + panel_destroy(output->panel); + wl_output_destroy(output->output); + wl_list_remove(&output->link); + + free(output); +} + +static void +desktop_destroy_outputs(struct desktop *desktop) +{ + struct output *tmp; + struct output *output; + + wl_list_for_each_safe(output, tmp, &desktop->outputs, link) + output_destroy(output); +} + static void create_output(struct desktop *desktop, uint32_t id) { @@ -1043,5 +1123,13 @@ int main(int argc, char *argv[]) display_run(desktop.display); + /* Cleanup */ + grab_surface_destroy(&desktop); + desktop_destroy_outputs(&desktop); + if (desktop.unlock_dialog) + unlock_dialog_destroy(desktop.unlock_dialog); + desktop_shell_destroy(desktop.shell); + display_destroy(desktop.display); + return 0; } diff --git a/clients/window.c b/clients/window.c index 575d3cb7..9a75a462 100644 --- a/clients/window.c +++ b/clients/window.c @@ -84,6 +84,7 @@ struct display { uint32_t serial; int display_fd; + uint32_t display_fd_events; uint32_t mask; struct task display_task; @@ -3727,7 +3728,14 @@ handle_display_data(struct task *task, uint32_t events) { struct display *display = container_of(task, struct display, display_task); - + + display->display_fd_events = events; + + if (events & EPOLLERR || events & EPOLLHUP) { + display_exit(display); + return; + } + wl_display_iterate(display->display, display->mask); } @@ -3751,7 +3759,8 @@ display_create(int argc, char *argv[]) d->epoll_fd = os_epoll_create_cloexec(); d->display_fd = wl_display_get_fd(d->display, event_mask_update, d); d->display_task.run = handle_display_data; - display_watch_fd(d, d->display_fd, EPOLLIN, &d->display_task); + display_watch_fd(d, d->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, + &d->display_task); wl_list_init(&d->deferred_list); wl_list_init(&d->input_list); @@ -3815,7 +3824,8 @@ void display_destroy(struct display *display) { if (!wl_list_empty(&display->window_list)) - fprintf(stderr, "toytoolkit warning: windows exist.\n"); + fprintf(stderr, "toytoolkit warning: %d windows exist.\n", + wl_list_length(&display->window_list)); if (!wl_list_empty(&display->deferred_list)) fprintf(stderr, "toytoolkit warning: deferred tasks exist.\n"); @@ -3845,7 +3855,10 @@ display_destroy(struct display *display) close(display->epoll_fd); - wl_display_flush(display->display); + if (!(display->display_fd_events & EPOLLERR) && + !(display->display_fd_events & EPOLLHUP)) + wl_display_flush(display->display); + wl_display_disconnect(display->display); free(display); }