diff --git a/CMakeLists.txt b/CMakeLists.txt index 7adfb462337d73520e9924b572e47776d6471f22..a633b94826072f9a0aa13f488abf9249486fe893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ find_package(SDL2) find_package(Threads) find_package(ZLIB) find_package(cJSON) +find_package(Systemd) # @TODO Turn into a find_package LIBUVC file. pkg_check_modules(LIBUVC libuvc) @@ -72,6 +73,7 @@ cmake_dependent_option(BUILD_WITH_EGL "Enable OpenGL on EGL Graphics API support cmake_dependent_option(BUILD_WITH_DBUS "Enable dbus support (for BLE support)" ON "DBUS_FOUND" OFF) cmake_dependent_option(BUILD_COMPOSITOR_MAIN "Build main compositor host" ON "BUILD_WITH_WAYLAND OR BUILD_WITH_XCB" OFF) cmake_dependent_option(XRT_BUILD_IPC "Build OpenXR runtime target" ON "BUILD_COMPOSITOR_MAIN" OFF) +cmake_dependent_option(XRT_HAVE_SYSTEMD "Enable systemd support (for socket activation of service)" ON "Systemd_FOUND AND XRT_BUILD_IPC" OFF) cmake_dependent_option(BUILD_TARGET_OPENXR "Build OpenXR runtime target" ON "BUILD_COMPOSITOR_MAIN OR XRT_BUILD_IPC" OFF) # Most users won't touch these. diff --git a/cmake/FindSystemd.cmake b/cmake/FindSystemd.cmake index 09d60115035a0ec1852dd2db8003f0aadcb5e05a..2daf9a74e8584a3547e2d792fd0e2a3388846096 100644 --- a/cmake/FindSystemd.cmake +++ b/cmake/FindSystemd.cmake @@ -15,6 +15,7 @@ # #============================================================================= # Copyright (c) 2015 Jari Vetoniemi +# Copyright (c) 2020 Collabora, Ltd. # # Distributed under the OSI-approved BSD License (the "License"); # @@ -24,17 +25,25 @@ #============================================================================= include(FeatureSummary) -set_package_properties(Systemd PROPERTIES - URL "http://freedesktop.org/wiki/Software/systemd/" - DESCRIPTION "System and Service Manager") +set_package_properties( + Systemd PROPERTIES + URL "http://freedesktop.org/wiki/Software/systemd/" + DESCRIPTION "System and Service Manager") find_package(PkgConfig) pkg_check_modules(PC_SYSTEMD QUIET libsystemd) -find_library(SYSTEMD_LIBRARIES NAMES systemd ${PC_SYSTEMD_LIBRARY_DIRS}) -find_path(SYSTEMD_INCLUDE_DIRS systemd/sd-login.h HINTS ${PC_SYSTEMD_INCLUDE_DIRS}) - -set(SYSTEMD_DEFINITIONS ${PC_SYSTEMD_CFLAGS_OTHER}) +find_library( + SYSTEMD_LIBRARY + NAMES systemd + HINTS ${PC_SYSTEMD_LIBRARY_DIRS}) +find_path(SYSTEMD_INCLUDE_DIR systemd/sd-login.h + HINTS ${PC_SYSTEMD_INCLUDE_DIRS}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SYSTEMD DEFAULT_MSG SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES) -mark_as_advanced(SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES SYSTEMD_DEFINITIONS) +find_package_handle_standard_args(Systemd DEFAULT_MSG SYSTEMD_INCLUDE_DIR + SYSTEMD_LIBRARY) +if(SYSTEMD_FOUND) + set(SYSTEMD_LIBRARIES ${SYSTEMD_LIBRARY}) + set(SYSTEMD_INCLUDE_DIRS ${SYSTEMD_INCLUDE_DIR}) + set(SYSTEMD_DEFINITIONS ${PC_SYSTEMD_CFLAGS_OTHER}) +endif() diff --git a/src/xrt/include/xrt/xrt_config_have.h.cmake_in b/src/xrt/include/xrt/xrt_config_have.h.cmake_in index dbff3c9952d48749d0451c8de4d442f6b652cd81..1feecbb6e575922eb62a1f78f466a2c509dd6ae0 100644 --- a/src/xrt/include/xrt/xrt_config_have.h.cmake_in +++ b/src/xrt/include/xrt/xrt_config_have.h.cmake_in @@ -26,3 +26,5 @@ #cmakedefine XRT_HAVE_SDL2 #cmakedefine XRT_HAVE_OPENHMD + +#cmakedefine XRT_HAVE_SYSTEMD diff --git a/src/xrt/ipc/CMakeLists.txt b/src/xrt/ipc/CMakeLists.txt index f0f5fd1e8dce249c3f85265372de5346334e1451..0dc4bda2f39013430f42fe3aa0d8344bf4d335dc 100644 --- a/src/xrt/ipc/CMakeLists.txt +++ b/src/xrt/ipc/CMakeLists.txt @@ -75,3 +75,10 @@ target_link_libraries(ipc_server PRIVATE aux_util rt ) + +if(XRT_HAVE_SYSTEMD) + target_include_directories(ipc_server PRIVATE + ${SYSTEMD_INCLUDE_DIRS}) + target_link_libraries(ipc_server PRIVATE + ${SYSTEMD_LIBRARIES}) +endif() diff --git a/src/xrt/ipc/ipc_server.h b/src/xrt/ipc/ipc_server.h index 55610201faa44657aa168234ed592555fb4f7df1..a51387720e3100233e81b9d8a8c76ed44ca0d199 100644 --- a/src/xrt/ipc/ipc_server.h +++ b/src/xrt/ipc/ipc_server.h @@ -156,6 +156,9 @@ struct ipc_server // Should we exit when a client disconnects. bool exit_on_disconnect; + //! Were we launched by socket activation, instead of explicitly? + bool launched_by_socket; + bool print_debug; bool print_spew; diff --git a/src/xrt/ipc/ipc_server_process.c b/src/xrt/ipc/ipc_server_process.c index b7ed653daaef7c5887fa99281bc1585071acb689..baa3e26d2d5292076f2b661c20de98dc2d8c794e 100644 --- a/src/xrt/ipc/ipc_server_process.c +++ b/src/xrt/ipc/ipc_server_process.c @@ -12,6 +12,7 @@ #include "xrt/xrt_device.h" #include "xrt/xrt_instance.h" #include "xrt/xrt_compositor.h" +#include "xrt/xrt_config_have.h" #include "util/u_var.h" #include "util/u_misc.h" @@ -36,6 +37,9 @@ #include <errno.h> #include <stdio.h> +#ifdef XRT_HAVE_SYSTEMD +#include <systemd/sd-daemon.h> +#endif /* * @@ -68,6 +72,7 @@ teardown_all(struct ipc_server *s) xrt_instance_destroy(&s->xinst); if (s->listen_socket > 0) { + // Close socket on exit close(s->listen_socket); s->listen_socket = -1; } @@ -174,8 +179,28 @@ init_shm(struct ipc_server *s) } static int -init_listen_socket(struct ipc_server *s) +get_systemd_socket(struct ipc_server *s, int *out_fd) +{ +#ifdef XRT_HAVE_SYSTEMD + // We may have been launched with socket activation + int num_fds = sd_listen_fds(0); + if (num_fds > 1) { + fprintf(stderr, + "Too many file descriptors passed by systemd.\n"); + return -1; + } + if (num_fds == 1) { + *out_fd = SD_LISTEN_FDS_START + 0; + s->launched_by_socket = true; + printf("Got existing socket from systemd.\n"); + } +#endif + return 0; +} +static int +create_listen_socket(struct ipc_server *s, int *out_fd) { + // no fd provided struct sockaddr_un addr; int fd, ret; @@ -202,9 +227,31 @@ init_listen_socket(struct ipc_server *s) close(fd); return ret; } + printf("Created listening socket.\n"); + *out_fd = fd; + return 0; +} + +static int +init_listen_socket(struct ipc_server *s) +{ + int fd = -1, ret; + s->listen_socket = -1; + + ret = get_systemd_socket(s, &fd); + if (ret < 0) { + return ret; + } + if (fd == -1) { + ret = create_listen_socket(s, &fd); + if (ret < 0) { + return ret; + } + } // All ok! s->listen_socket = fd; + printf("Listening socket is fd %d\n", s->listen_socket); return fd; } @@ -221,12 +268,17 @@ init_epoll(struct ipc_server *s) struct epoll_event ev = {0}; - ev.events = EPOLLIN; - ev.data.fd = 0; // stdin - ret = epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, 0, &ev); - if (ret < 0) { - fprintf(stderr, "ERROR: epoll_ctl(stdin) failed '%i'\n", ret); - return ret; + if (!s->launched_by_socket) { + // Can't do this when launched by systemd socket activation by + // default + ev.events = EPOLLIN; + ev.data.fd = 0; // stdin + ret = epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, 0, &ev); + if (ret < 0) { + fprintf(stderr, "ERROR: epoll_ctl(stdin) failed '%i'\n", + ret); + return ret; + } } ev.events = EPOLLIN;