ubusd: fix systemd socket activation support
authorMatthias Schiffer <mschiffer@universe-factory.net>
Tue, 24 May 2016 00:01:48 +0000 (02:01 +0200)
committerJohn Crispin <john@phrozen.org>
Wed, 1 Jun 2016 09:32:46 +0000 (11:32 +0200)
62cdfc3 added systemd units including a ubus.socket unit, but didn't
actually add socket activation support to ubusd. This would cause the first
connection that activated ubusd to hang (as ubusd ignored it), and stopping
ubusd would break it completely (as ubusd removed the socket file).

The ENABLE_SYSTEMD default is changed to OFF as the socket activation uses
libsystemd, so setting ENABLE_SYSTEMD to ON will now require libsystemd.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
CMakeLists.txt
ubusd.c

index e21a04698913fe63b06980380ac2aacd39189e6a..faab342560ea8970b66d09e1f56d56ee52a82a9e 100644 (file)
@@ -5,7 +5,7 @@ ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -Wmissing-declarations)
 
 OPTION(BUILD_LUA "build Lua plugin" ON)
 OPTION(BUILD_EXAMPLES "build examples" ON)
-OPTION(ENABLE_SYSTEMD "systemd support" ON)
+OPTION(ENABLE_SYSTEMD "systemd support" OFF)
 
 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
 SET(UBUS_UNIX_SOCKET "/var/run/ubus.sock")
@@ -60,8 +60,13 @@ SET(UBUSD_BINARY "${CMAKE_INSTALL_PREFIX}/sbin/ubusd")
 # do this after the installs so we have the proper paths
 IF(ENABLE_SYSTEMD)
   INCLUDE(FindPkgConfig)
-  PKG_CHECK_MODULES(SYSTEMD systemd)
-  IF(SYSTEMD_FOUND)
-    ADD_SUBDIRECTORY(systemd)
-  ENDIF()
+  PKG_CHECK_MODULES(SYSTEMD libsystemd REQUIRED)
+
+  SET_PROPERTY(TARGET ubusd APPEND PROPERTY COMPILE_FLAGS "${SYSTEMD_CFLAGS}")
+  SET_PROPERTY(TARGET ubusd APPEND PROPERTY LINK_FLAGS "${SYSTEMD_LDFLAGS}")
+  SET_PROPERTY(TARGET ubusd APPEND PROPERTY INCLUDE_DIRECTORIES ${SYSTEMD_INCLUDE_DIRS})
+  TARGET_LINK_LIBRARIES(ubusd ${SYSTEMD_LIBRARIES})
+  ADD_DEFINITIONS( -DENABLE_SYSTEMD)
+
+  ADD_SUBDIRECTORY(systemd)
 ENDIF()
diff --git a/ubusd.c b/ubusd.c
index 7279a706f47e44caf92d5433326b5b733bb1b440..5b1d52c808924c1e40eb3d699225db981ad9e1e3 100644 (file)
--- a/ubusd.c
+++ b/ubusd.c
@@ -22,6 +22,9 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
+#ifdef ENABLE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
 
 #include <libubox/blob.h>
 #include <libubox/uloop.h>
@@ -380,8 +383,12 @@ static void sighup_handler(int sig)
 int main(int argc, char **argv)
 {
        const char *ubus_socket = UBUS_UNIX_SOCKET;
+       bool remove_socket = true;
        int ret = 0;
        int ch;
+#ifdef ENABLE_SYSTEMD
+       int n_fds;
+#endif
 
        signal(SIGPIPE, SIG_IGN);
        signal(SIGHUP, sighup_handler);
@@ -402,19 +409,37 @@ int main(int argc, char **argv)
                }
        }
 
-       unlink(ubus_socket);
-       umask(0111);
-       server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, ubus_socket, NULL);
-       if (server_fd.fd < 0) {
-               perror("usock");
-               ret = -1;
+#ifdef ENABLE_SYSTEMD
+       n_fds = sd_listen_fds(1);
+       if (n_fds > 1) {
+               fprintf(stderr, "Too many file descriptors received.\n");
+               ret = -1;
                goto out;
+       } else if (n_fds == 1) {
+               server_fd.fd = SD_LISTEN_FDS_START + 0;
+               fcntl(server_fd.fd, F_SETFD, fcntl(server_fd.fd, F_GETFD) | FD_CLOEXEC);
+               fcntl(server_fd.fd, F_SETFL, fcntl(server_fd.fd, F_GETFL) | O_NONBLOCK);
+
+               remove_socket = false;
+       } else
+#endif
+       {
+               unlink(ubus_socket);
+               umask(0111);
+               server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, ubus_socket, NULL);
+               if (server_fd.fd < 0) {
+                       perror("usock");
+                       ret = -1;
+                       goto out;
+               }
        }
        uloop_fd_add(&server_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
        ubusd_acl_load();
 
        uloop_run();
-       unlink(ubus_socket);
+
+       if (remove_socket)
+               unlink(ubus_socket);
 
 out:
        uloop_done();