xserver: Clean up lockfile creation a bit
This commit is contained in:
@@ -648,14 +648,69 @@ bind_to_unix_socket(int display)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_lockfile(int display, char *lockfile, size_t lsize)
|
||||||
|
{
|
||||||
|
char pid[16], *end;
|
||||||
|
int fd, size;
|
||||||
|
pid_t other;
|
||||||
|
|
||||||
|
snprintf(lockfile, lsize, "/tmp/.X%d-lock", display);
|
||||||
|
fd = open(lockfile, O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL, 0444);
|
||||||
|
if (fd < 0 && errno == EEXIST) {
|
||||||
|
fd = open(lockfile, O_CLOEXEC, O_RDONLY);
|
||||||
|
if (fd < 0 || read(fd, pid, 11) != 11) {
|
||||||
|
fprintf(stderr, "can't read lock file %s: %s\n",
|
||||||
|
lockfile, strerror(errno));
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
other = strtol(pid, &end, 0);
|
||||||
|
if (end != pid + 10) {
|
||||||
|
fprintf(stderr, "can't parse lock file %s\n",
|
||||||
|
lockfile);
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kill(other, 0) < 0 && errno == ESRCH) {
|
||||||
|
/* stale lock file; unlink and try again */
|
||||||
|
fprintf(stderr,
|
||||||
|
"unlinking stale lock file %s\n", lockfile);
|
||||||
|
unlink(lockfile);
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
} else if (fd < 0) {
|
||||||
|
fprintf(stderr, "failed to create lock file %s: %s\n",
|
||||||
|
lockfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subtle detail: we use the pid of the wayland
|
||||||
|
* compositor, not the xserver in the lock file. */
|
||||||
|
size = snprintf(pid, sizeof pid, "%10d\n", getpid());
|
||||||
|
if (write(fd, pid, size) != size) {
|
||||||
|
unlink(lockfile);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wlsc_xserver_init(struct wlsc_compositor *compositor)
|
wlsc_xserver_init(struct wlsc_compositor *compositor)
|
||||||
{
|
{
|
||||||
struct wl_display *display = compositor->wl_display;
|
struct wl_display *display = compositor->wl_display;
|
||||||
struct wlsc_xserver *mxs;
|
struct wlsc_xserver *mxs;
|
||||||
char lockfile[256], pid[16], *end;
|
char lockfile[256];
|
||||||
pid_t other;
|
|
||||||
int fd, size;
|
|
||||||
|
|
||||||
mxs = malloc(sizeof *mxs);
|
mxs = malloc(sizeof *mxs);
|
||||||
memset(mxs, 0, sizeof *mxs);
|
memset(mxs, 0, sizeof *mxs);
|
||||||
@@ -664,70 +719,34 @@ wlsc_xserver_init(struct wlsc_compositor *compositor)
|
|||||||
mxs->wl_display = display;
|
mxs->wl_display = display;
|
||||||
|
|
||||||
mxs->display = 0;
|
mxs->display = 0;
|
||||||
do {
|
|
||||||
snprintf(lockfile, sizeof lockfile,
|
|
||||||
"/tmp/.X%d-lock", mxs->display);
|
|
||||||
fd = open(lockfile,
|
|
||||||
O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL, 0444);
|
|
||||||
if (fd < 0 && errno == EEXIST) {
|
|
||||||
fd = open(lockfile, O_CLOEXEC, O_RDONLY);
|
|
||||||
if (fd < 0 || read(fd, pid, 11) != 11) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"can't read lock file %s: %s\n",
|
|
||||||
lockfile, strerror(errno));
|
|
||||||
mxs->display++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
other = strtol(pid, &end, 0);
|
|
||||||
if (end != pid + 10) {
|
|
||||||
fprintf(stderr, "can't parse lock file %s\n",
|
|
||||||
lockfile);
|
|
||||||
mxs->display++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kill(other, 0) < 0 && errno == ESRCH) {
|
|
||||||
/* stale lock file; unlink and try again */
|
|
||||||
fprintf(stderr,
|
|
||||||
"unlinking stale lock file %s\n",
|
|
||||||
lockfile);
|
|
||||||
unlink(lockfile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (create_lockfile(mxs->display, lockfile, sizeof lockfile) < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
goto retry;
|
||||||
|
} else if (errno == EEXIST) {
|
||||||
mxs->display++;
|
mxs->display++;
|
||||||
continue;
|
goto retry;
|
||||||
} else if (fd < 0) {
|
} else {
|
||||||
fprintf(stderr, "failed to create lock file %s: %s\n",
|
|
||||||
lockfile, strerror(errno));
|
|
||||||
free(mxs);
|
free(mxs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Subtle detail: we use the pid of the wayland
|
mxs->abstract_fd = bind_to_abstract_socket(mxs->display);
|
||||||
* compositor, not the xserver in the lock file. */
|
if (mxs->abstract_fd < 0 && errno == EADDRINUSE) {
|
||||||
size = snprintf(pid, sizeof pid, "%10d\n", getpid());
|
mxs->display++;
|
||||||
write(fd, pid, size);
|
unlink(lockfile);
|
||||||
close(fd);
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
mxs->abstract_fd = bind_to_abstract_socket(mxs->display);
|
mxs->unix_fd = bind_to_unix_socket(mxs->display);
|
||||||
if (mxs->abstract_fd < 0 && errno == EADDRINUSE) {
|
if (mxs->unix_fd < 0) {
|
||||||
mxs->display++;
|
unlink(lockfile);
|
||||||
unlink(lockfile);
|
close(mxs->abstract_fd);
|
||||||
continue;
|
free(mxs);
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
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);
|
fprintf(stderr, "xserver listening on display :%d\n", mxs->display);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user