From fa5f7b11918727a2665e16bcd1a61ad49b0ae195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 13 Apr 2012 09:53:15 -0400 Subject: [PATCH] server: Add client destroy signal --- src/wayland-server.c | 18 +++++++++ src/wayland-server.h | 9 ++++- tests/Makefile.am | 9 ++++- tests/client-test.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 tests/client-test.c diff --git a/src/wayland-server.c b/src/wayland-server.c index e9a3ff97..8ca27bd9 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -63,6 +63,7 @@ struct wl_client { uint32_t mask; struct wl_list link; struct wl_map objects; + struct wl_signal destroy_signal; struct ucred ucred; int error; }; @@ -336,6 +337,7 @@ wl_client_create(struct wl_display *display, int fd) return NULL; } + wl_signal_init(&client->destroy_signal); bind_display(client, display, 1, 1); wl_list_insert(display->client_list.prev, &client->link); @@ -409,6 +411,20 @@ wl_resource_destroy(struct wl_resource *resource) } } +WL_EXPORT void +wl_client_add_destroy_listener(struct wl_client *client, + struct wl_listener *listener) +{ + wl_signal_add(&client->destroy_signal, listener); +} + +WL_EXPORT struct wl_listener * +wl_client_get_destroy_listener(struct wl_client *client, + wl_notify_func_t notify) +{ + return wl_signal_get(&client->destroy_signal, notify); +} + WL_EXPORT void wl_client_destroy(struct wl_client *client) { @@ -416,6 +432,8 @@ wl_client_destroy(struct wl_client *client) printf("disconnect from client %p\n", client); + wl_signal_emit(&client->destroy_signal, client); + wl_client_flush(client); wl_map_for_each(&client->objects, destroy_resource, &serial); wl_map_release(&client->objects); diff --git a/src/wayland-server.h b/src/wayland-server.h index f9f1b5f6..bda3f1bf 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -75,6 +75,8 @@ int wl_event_loop_get_fd(struct wl_event_loop *loop); struct wl_client; struct wl_display; struct wl_input_device; +struct wl_listener; +typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data); struct wl_display *wl_display_create(void); void wl_display_destroy(struct wl_display *display); @@ -106,6 +108,11 @@ void wl_client_flush(struct wl_client *client); void wl_client_get_credentials(struct wl_client *client, pid_t *pid, uid_t *uid, gid_t *gid); +void wl_client_add_destroy_listener(struct wl_client *client, + struct wl_listener *listener); +struct wl_listener *wl_client_get_destroy_listener(struct wl_client *client, + wl_notify_func_t notify); + struct wl_resource * wl_client_add_object(struct wl_client *client, const struct wl_interface *interface, @@ -117,7 +124,7 @@ wl_client_new_object(struct wl_client *client, struct wl_listener { struct wl_list link; - void (*notify)(struct wl_listener *listener, void *data); + wl_notify_func_t notify; }; struct wl_signal { diff --git a/tests/Makefile.am b/tests/Makefile.am index d7d12e0e..cc4b9ccc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,13 +1,20 @@ TESTS = $(check_PROGRAMS) -check_PROGRAMS = array-test map-test list-test connection-test event-loop-test +check_PROGRAMS = \ + array-test \ + map-test \ + list-test \ + connection-test \ + event-loop-test \ + client-test map_test_SOURCES = map-test.c test-runner.c test-runner.h array_test_SOURCES = array-test.c test-runner.c list_test_SOURCES = list-test.c test-runner.c connection_test_SOURCES = connection-test.c test-runner.c event_loop_test_SOURCES = event-loop-test.c test-runner.c +client_test_SOURCES = client-test.c test-runner.c AM_CFLAGS = $(GCC_CFLAGS) LDADD = $(top_builddir)/src/libwayland-util.la \ diff --git a/tests/client-test.c b/tests/client-test.c new file mode 100644 index 00000000..dd2190f6 --- /dev/null +++ b/tests/client-test.c @@ -0,0 +1,87 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../src/wayland-server.h" +#include "test-runner.h" + +struct client_destroy_listener { + struct wl_listener listener; + int done; +}; + +static void +client_destroy_notify(struct wl_listener *l, void *data) +{ + struct client_destroy_listener *listener = + container_of(l, struct client_destroy_listener, listener); + + listener->done = 1; +} + +TEST(client_destroy_listener) +{ + struct wl_display *display; + struct wl_client *client; + struct client_destroy_listener a, b; + int s[2]; + + assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + display = wl_display_create(); + assert(display); + client = wl_client_create(display, s[0]); + assert(client); + + a.listener.notify = client_destroy_notify; + a.done = 0; + wl_client_add_destroy_listener(client, &a.listener); + + assert(wl_client_get_destroy_listener(client, client_destroy_notify) == + &a.listener); + + b.listener.notify = client_destroy_notify; + b.done = 0; + wl_client_add_destroy_listener(client, &b.listener); + + wl_list_remove(&a.listener.link); + + wl_client_destroy(client); + + assert(!a.done); + assert(b.done); + + close(s[0]); + close(s[1]); + + wl_display_destroy(display); +} +