ipc: Add ability for service to be launched by systemd socket activation.

This commit is contained in:
Ryan Pavlik 2020-05-01 15:55:12 -05:00
parent 67a2c26295
commit 5935fad73b
6 changed files with 91 additions and 16 deletions

View file

@ -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.

View file

@ -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()

View file

@ -26,3 +26,5 @@
#cmakedefine XRT_HAVE_SDL2
#cmakedefine XRT_HAVE_OPENHMD
#cmakedefine XRT_HAVE_SYSTEMD

View file

@ -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()

View file

@ -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;

View file

@ -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;