xserver: Listen on abstract X socket too

And try the next display if binding fails.
This commit is contained in:
Kristian Høgsberg 2011-08-11 17:27:56 -04:00
parent 2116b89156
commit 534222b4d9

View File

@ -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);
close(mxs->fd);
continue;
}
mxs->unix_fd = bind_to_unix_socket(mxs->display);
if (mxs->unix_fd < 0) {
unlink(lockfile);
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);
}