summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2011-04-13 09:38:29 +0200
committerKristian Høgsberg <krh@bitplanet.net>2011-04-13 10:42:27 -0400
commitf04e05ad76cd6af890b7b741a9e0f5181bd0ac10 (patch)
treec269f811259d6c05475ac06077b892d08201afd1
parent4378a80b083f6ad3c5a3eaadd6f55eb14740dbbf (diff)
Add lockfile to the socket
This uses flock to detect if there is a process that is active. If not then it unlinks the socket file if it exists, so that bind won't fail
-rw-r--r--wayland/wayland-server.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/wayland/wayland-server.c b/wayland/wayland-server.c
index 549e069..66ad861 100644
--- a/wayland/wayland-server.c
+++ b/wayland/wayland-server.c
@@ -36,6 +36,8 @@
#include <assert.h>
#include <sys/time.h>
#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
#include <ffi.h>
#include "wayland-server.h"
@@ -44,7 +46,9 @@
struct wl_socket {
int fd;
+ int fd_lock;
struct sockaddr_un addr;
+ char lock_addr[113];
struct wl_list link;
};
@@ -577,6 +581,8 @@ wl_display_destroy(struct wl_display *display)
wl_list_for_each_safe(s, next, &display->socket_list, link) {
close(s->fd);
unlink(s->addr.sun_path);
+ close(s->fd_lock);
+ unlink(s->lock_addr);
free(s);
}
@@ -660,6 +666,48 @@ socket_data(int fd, uint32_t mask, void *data)
wl_client_create(display, client_fd);
}
+static int
+get_socket_lock(struct wl_socket *socket, socklen_t name_size)
+{
+ struct stat socket_stat;
+ int lock_size = name_size + 5;
+
+ snprintf(socket->lock_addr, lock_size,
+ "%s.lock", socket->addr.sun_path);
+
+ socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC,
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
+
+ if (socket->fd_lock < 0) {
+ fprintf(stderr,
+ "unable to open lockfile %s check permissions\n",
+ socket->lock_addr);
+ return -1;
+ }
+
+ if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
+ fprintf(stderr,
+ "unable to lock lockfile %s, maybe another compositor is running\n",
+ socket->lock_addr);
+ close(socket->fd_lock);
+ return -1;
+ }
+
+ if (stat(socket->addr.sun_path, &socket_stat) < 0 ) {
+ if (errno != ENOENT) {
+ fprintf(stderr, "did not manage to stat file %s\n",
+ socket->addr.sun_path);
+ close(socket->fd_lock);
+ return -1;
+ }
+ } else if (socket_stat.st_mode & S_IWUSR ||
+ socket_stat.st_mode & S_IWGRP) {
+ unlink(socket->addr.sun_path);
+ }
+
+ return 0;
+}
+
WL_EXPORT int
wl_display_add_socket(struct wl_display *display, const char *name)
{
@@ -696,6 +744,12 @@ wl_display_add_socket(struct wl_display *display, const char *name)
"%s/%s", runtime_dir, name) + 1;
fprintf(stderr, "using socket %s\n", s->addr.sun_path);
+ if (get_socket_lock(s,name_size) < 0) {
+ close(s->fd);
+ free(s);
+ return -1;
+ }
+
size = offsetof (struct sockaddr_un, sun_path) + name_size;
if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
close(s->fd);