[PATCH 4/5] server: Add support for systemd socket activation

Benjamin Franzke benjaminfranzke at googlemail.com
Wed Feb 27 03:10:19 PST 2013


This is acquring the socket, omit bind and listen,
and not touching (e.g. removing) the socket path
since thats managed by systemd.
---
 src/wayland-server.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 9ac0a71..c61291e 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -45,6 +45,7 @@
 #include "wayland-server.h"
 #include "wayland-server-protocol.h"
 #include "wayland-os.h"
+#include "sd-daemon.h"
 
 /* This is the size of the char array in struct sock_addr_un.
    No Wayland socket can be created with a path longer than this,
@@ -59,6 +60,7 @@
 struct wl_socket {
 	int fd;
 	int fd_lock;
+	int is_systemd;
 	struct sockaddr_un addr;
 	char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
 	struct wl_list link;
@@ -1123,7 +1125,8 @@ wl_display_destroy(struct wl_display *display)
 
 	wl_list_for_each_safe(s, next, &display->socket_list, link) {
 		wl_event_source_remove(s->source);
-		unlink(s->addr.sun_path);
+		if (!s->is_systemd)
+			unlink(s->addr.sun_path);
 		close(s->fd);
 		unlink(s->lock_addr);
 		close(s->fd_lock);
@@ -1277,6 +1280,9 @@ get_socket_lock(struct wl_socket *socket)
 		return -1;
 	}
 
+	if (socket->is_systemd)
+		return fd_lock;
+
 	if (stat(socket->addr.sun_path, &socket_stat) < 0 ) {
 		if (errno != ENOENT) {
 			wl_log("did not manage to stat file %s\n",
@@ -1297,6 +1303,9 @@ init_socket(struct wl_socket *s, int name_size)
 {
 	socklen_t size;
 
+	if (s->is_systemd)
+		return 0;
+
 	size = offsetof (struct sockaddr_un, sun_path) + name_size;
 	if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
 		wl_log("bind() failed with error: %m\n");
@@ -1312,6 +1321,30 @@ init_socket(struct wl_socket *s, int name_size)
 	return 0;
 }
 
+static int
+acquire_systemd_socket(struct wl_socket *s, int type)
+{
+	int n, fd;
+
+	s->is_systemd = 0;
+	n = sd_listen_fds(0);
+	if (n <= 0) {
+		if (n < 0)
+			wl_log("failed to acquire socket from systemd: %m\n");
+		return -1;
+	}
+
+	for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
+		if (sd_is_socket_unix(fd, type, 1, s->addr.sun_path, 0) == 1) {
+			s->is_systemd = 1;
+			s->fd = fd;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
 WL_EXPORT int
 wl_display_add_socket(struct wl_display *display, const char *name)
 {
@@ -1354,7 +1387,9 @@ wl_display_add_socket(struct wl_display *display, const char *name)
 		return -1;
 	};
 
-	s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
+	if (acquire_systemd_socket(s, SOCK_STREAM) < 0)
+		s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
+
 	if (s->fd < 0) {
 		free(s);
 		return -1;
@@ -1380,7 +1415,8 @@ wl_display_add_socket(struct wl_display *display, const char *name)
 					 WL_EVENT_READABLE,
 					 socket_data, display);
 	if (s->source == NULL) {
-		unlink(s->addr.sun_path);
+		if (!s->is_systemd)
+			unlink(s->addr.sun_path);
 		close(s->fd);
 		unlink(s->lock_addr);
 		close(s->fd_lock);
-- 
1.7.12.4



More information about the wayland-devel mailing list