From 534222b4d92012261aec6ae32c3aba3894c6d00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 11 Aug 2011 17:27:56 -0400 Subject: xserver: Listen on abstract X socket too And try the next display if binding fails. --- compositor/xserver-launcher.c | 143 +++++++++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 38 deletions(-) diff --git a/compositor/xserver-launcher.c b/compositor/xserver-launcher.c index a3c7fd8a..a5e66299 100644 --- a/compositor/xserver-launcher.c +++ b/compositor/xserver-launcher.c @@ -55,12 +55,12 @@ struct xserver { struct wlsc_xserver { struct wl_display *wl_display; struct wl_event_loop *loop; - struct wl_event_source *source; struct wl_event_source *sigchld_source; struct wl_client *client; - int fd; - struct sockaddr_un addr; - char lock_addr[113]; + int abstract_fd; + struct wl_event_source *abstract_source; + int unix_fd; + struct wl_event_source *unix_source; int display; struct wlsc_process process; @@ -470,7 +470,11 @@ wlsc_xserver_bind(struct wl_client *client, wl_client_post_event(wxs->client, &wxs->xserver.object, - XSERVER_LISTEN_SOCKET, wxs->fd); + XSERVER_LISTEN_SOCKET, wxs->abstract_fd); + + wl_client_post_event(wxs->client, + &wxs->xserver.object, + XSERVER_LISTEN_SOCKET, wxs->unix_fd); } static int @@ -522,7 +526,8 @@ wlsc_xserver_handle_event(int listen_fd, uint32_t mask, void *data) wlsc_watch_process(&mxs->process); - wl_event_source_remove(mxs->source); + wl_event_source_remove(mxs->abstract_source); + wl_event_source_remove(mxs->unix_source); break; case -1: @@ -541,8 +546,15 @@ wlsc_xserver_cleanup(struct wlsc_process *process, int status) fprintf(stderr, "xserver exited, code %d\n", status); mxs->process.pid = 0; - mxs->source = - wl_event_loop_add_fd(mxs->loop, mxs->fd, WL_EVENT_READABLE, + + mxs->abstract_source = + wl_event_loop_add_fd(mxs->loop, mxs->abstract_fd, + WL_EVENT_READABLE, + wlsc_xserver_handle_event, mxs); + + mxs->unix_source = + wl_event_loop_add_fd(mxs->loop, mxs->unix_fd, + WL_EVENT_READABLE, wlsc_xserver_handle_event, mxs); } @@ -574,27 +586,82 @@ static const struct xserver_interface xserver_implementation = { xserver_set_window_id }; +static int +bind_to_abstract_socket(int display) +{ + struct sockaddr_un addr; + socklen_t size, name_size; + int fd; + + fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) + return -1; + + addr.sun_family = AF_LOCAL; + name_size = snprintf(addr.sun_path, sizeof addr.sun_path, + "%c/tmp/.X11-unix/X%d", 0, display); + size = offsetof(struct sockaddr_un, sun_path) + name_size; + if (bind(fd, (struct sockaddr *) &addr, size) < 0) { + fprintf(stderr, "failed to bind to @%s: %s\n", + addr.sun_path + 1, strerror(errno)); + close(fd); + return -1; + } + + if (listen(fd, 1) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static int +bind_to_unix_socket(int display) +{ + struct sockaddr_un addr; + socklen_t size, name_size; + int fd; + + fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) + return -1; + + addr.sun_family = AF_LOCAL; + name_size = snprintf(addr.sun_path, sizeof addr.sun_path, + "/tmp/.X11-unix/X%d", display) + 1; + size = offsetof(struct sockaddr_un, sun_path) + name_size; + unlink(addr.sun_path); + if (bind(fd, (struct sockaddr *) &addr, size) < 0) { + fprintf(stderr, "failed to bind to %s (%s)\n", + addr.sun_path, strerror(errno)); + close(fd); + return -1; + } + + if (listen(fd, 1) < 0) { + unlink(addr.sun_path); + close(fd); + return -1; + } + + return fd; +} + int wlsc_xserver_init(struct wlsc_compositor *compositor) { struct wl_display *display = compositor->wl_display; struct wlsc_xserver *mxs; char lockfile[256], pid[16], *end; - socklen_t size, name_size; pid_t other; - int fd; + int fd, size; mxs = malloc(sizeof *mxs); memset(mxs, 0, sizeof *mxs); mxs->process.cleanup = wlsc_xserver_cleanup; mxs->wl_display = display; - mxs->addr.sun_family = AF_LOCAL; - mxs->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (mxs->fd < 0) { - free(mxs); - return -1; - } mxs->display = 0; do { @@ -634,7 +701,6 @@ wlsc_xserver_init(struct wlsc_compositor *compositor) } else if (fd < 0) { fprintf(stderr, "failed to create lock file %s: %s\n", lockfile, strerror(errno)); - close(mxs->fd); free(mxs); return -1; } @@ -645,35 +711,34 @@ wlsc_xserver_init(struct wlsc_compositor *compositor) write(fd, pid, size); close(fd); - name_size = snprintf(mxs->addr.sun_path, - sizeof mxs->addr.sun_path, - "/tmp/.X11-unix/X%d", mxs->display) + 1; - size = offsetof(struct sockaddr_un, sun_path) + name_size; - unlink(mxs->addr.sun_path); - if (bind(mxs->fd, (struct sockaddr *) &mxs->addr, size) < 0) { - fprintf(stderr, "failed to bind to %s (%s)\n", - mxs->addr.sun_path, strerror(errno)); + mxs->abstract_fd = bind_to_abstract_socket(mxs->display); + if (mxs->abstract_fd < 0 && errno == EADDRINUSE) { + mxs->display++; + unlink(lockfile); + continue; + } + + mxs->unix_fd = bind_to_unix_socket(mxs->display); + if (mxs->unix_fd < 0) { unlink(lockfile); - close(mxs->fd); + close(mxs->abstract_fd); free(mxs); return -1; } + break; } while (errno != 0); fprintf(stderr, "xserver listening on display :%d\n", mxs->display); - if (listen(mxs->fd, 1) < 0) { - unlink(mxs->addr.sun_path); - unlink(lockfile); - close(mxs->fd); - free(mxs); - return -1; - } - mxs->loop = wl_display_get_event_loop(display); - mxs->source = - wl_event_loop_add_fd(mxs->loop, mxs->fd, WL_EVENT_READABLE, + mxs->abstract_source = + wl_event_loop_add_fd(mxs->loop, mxs->abstract_fd, + WL_EVENT_READABLE, + wlsc_xserver_handle_event, mxs); + mxs->unix_source = + wl_event_loop_add_fd(mxs->loop, mxs->unix_fd, + WL_EVENT_READABLE, wlsc_xserver_handle_event, mxs); mxs->xserver.object.interface = &xserver_interface; @@ -698,7 +763,9 @@ wlsc_xserver_destroy(struct wlsc_compositor *compositor) unlink(path); snprintf(path, sizeof path, "/tmp/.X11-unix/X%d", wxs->display); unlink(path); - close(wxs->fd); - wl_event_source_remove(wxs->source); + close(wxs->abstract_fd); + wl_event_source_remove(wxs->abstract_source); + close(wxs->unix_fd); + wl_event_source_remove(wxs->unix_source); free(wxs); } -- cgit v1.2.1