desktop-shell: destroy data before exiting.
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Wed, 3 Oct 2012 04:12:35 +0000 (21:12 -0700)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 4 Oct 2012 15:37:40 +0000 (11:37 -0400)
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 <ullysses.a.eoff@intel.com>
clients/desktop-shell.c
clients/window.c

index 588dc1c..dc43652 100644 (file)
@@ -372,6 +372,16 @@ clock_timer_reset(struct panel_clock *clock)
 }
 
 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)
 {
        struct panel_clock *clock;
@@ -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)
 {
@@ -912,6 +964,13 @@ grab_surface_enter_handler(struct widget *widget, struct input *input,
 }
 
 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)
 {
        struct wl_surface *s;
@@ -933,6 +992,27 @@ grab_surface_create(struct desktop *desktop)
 }
 
 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)
 {
        struct output *output;
@@ -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;
 }
index 575d3cb..9a75a46 100644 (file)
@@ -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);
 }