summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-08-11 17:27:56 -0400
committerKristian Høgsberg <krh@bitplanet.net>2011-08-11 17:27:56 -0400
commit534222b4d92012261aec6ae32c3aba3894c6d00b (patch)
tree21f0e6d3852404b9942dce6ebb16fd0a5f064b13
parent2116b891568cc2f86ad375177ad84b286b90d84a (diff)
downloadweston-534222b4d92012261aec6ae32c3aba3894c6d00b.tar.gz
xserver: Listen on abstract X socket too
And try the next display if binding fails.
-rw-r--r--compositor/xserver-launcher.c143
1 files 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);
}