#include <assert.h>
#include <sys/time.h>
#include <fcntl.h>
+#include <sys/eventfd.h>
#include <sys/file.h>
#include <sys/stat.h>
wl_display_global_filter_func_t global_filter;
void *global_filter_data;
+
+ int terminate_efd;
+ struct wl_event_source *term_source;
};
struct wl_global {
return 0;
}
+static int
+handle_display_terminate(int fd, uint32_t mask, void *data) {
+ uint64_t term_event;
+
+ if (read(fd, &term_event, sizeof(term_event)) < 0 && errno != EAGAIN)
+ return -1;
+
+ return 0;
+}
+
/** Create Wayland display object.
*
* \return The Wayland display object. Null if failed to create
return NULL;
}
+ display->terminate_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+ if (display->terminate_efd < 0)
+ goto err_eventfd;
+
+ display->term_source = wl_event_loop_add_fd(display->loop,
+ display->terminate_efd,
+ WL_EVENT_READABLE,
+ handle_display_terminate,
+ NULL);
+
+ if (display->term_source == NULL)
+ goto err_term_source;
+
wl_list_init(&display->global_list);
wl_list_init(&display->socket_list);
wl_list_init(&display->client_list);
wl_array_init(&display->additional_shm_formats);
return display;
+
+err_term_source:
+ close(display->terminate_efd);
+err_eventfd:
+ wl_event_loop_destroy(display->loop);
+ free(display);
+ return NULL;
}
static void
wl_list_for_each_safe(s, next, &display->socket_list, link) {
wl_socket_destroy(s);
}
+
+ close(display->terminate_efd);
+ wl_event_source_remove(display->term_source);
+
wl_event_loop_destroy(display->loop);
wl_list_for_each_safe(global, gnext, &display->global_list, link)
WL_EXPORT void
wl_display_terminate(struct wl_display *display)
{
+ int ret;
+ uint64_t terminate = 1;
+
display->run = 0;
+
+ ret = write(display->terminate_efd, &terminate, sizeof(terminate));
+ assert (ret >= 0 || errno == EAGAIN);
}
WL_EXPORT void
display_destroy(d);
}
+
+static void
+terminate_display(void *arg)
+{
+ struct wl_display *wl_display = arg;
+ wl_display_terminate(wl_display);
+}
+
+TEST(no_source_terminate)
+{
+ struct display *d;
+ struct wl_event_loop *loop;
+
+ d = display_create();
+ loop = wl_display_get_event_loop(d->wl_display);
+
+ wl_event_loop_add_idle(loop, terminate_display, d->wl_display);
+
+ display_run(d);
+ display_destroy(d);
+}