From 34471d85fca14a5ec359d2d06a8d7018cb23beb2 Mon Sep 17 00:00:00 2001 From: Alexander Mohr Date: Wed, 5 Oct 2022 10:23:44 +0200 Subject: systemd: add support for socket activation via systemd (#401) dlt-daemon now support activation via systemd socket. This allows dlt-daemon to be started as soon as an application is requesting access to the dlt socket. This commits implements opening the socket only when UNIX_SOCKET is used for IPC Signed-off-by: Alexander Mohr Signed-off-by: Alexander Mohr --- CMakeLists.txt | 11 +++++++- src/daemon/CMakeLists.txt | 3 +++ src/daemon/dlt_daemon_unix_socket.c | 50 +++++++++++++++++++++++++++++++++++++ systemd/CMakeLists.txt | 6 +++++ systemd/dlt.socket.cmake | 8 ++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100755 systemd/dlt.socket.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 49494af..2bcad1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ option(BUILD_SHARED_LIBS "Set to OFF to build static libraries" option(WITH_SYSTEMD "Set to ON to create unit files and systemd check on dlt-daemon startup" OFF) option(WITH_SYSTEMD_WATCHDOG "Set to ON to use the systemd watchdog in dlt-daemon" OFF) option(WITH_SYSTEMD_JOURNAL "Set to ON to use the systemd journal in dlt-system" OFF) +option(WITH_SYSTEMD_SOCKET_ACTIVATION "Set to ON to use systemd socket activation" OFF) option(WITH_DOC "Set to ON to build documentation target" OFF) option(WITH_MAN "Set to ON to build man pages" OFF) option(WITH_CHECK_CONFIG_FILE "Set to ON to create a configure file of CheckIncludeFiles and CheckFunctionExists" OFF) @@ -92,6 +93,7 @@ option(WITH_EXTENDED_FILTERING "Set to OFF to build without extended filtering. option(WITH_DLT_DAEMON_VSOCK_IPC "Set to ON to enable VSOCK support in daemon" OFF) option(WITH_DLT_LIB_VSOCK_IPC "Set to ON to enable VSOCK support in library (DLT_IPC is not used in library)" OFF) + set(DLT_VSOCK_PORT "13490" CACHE STRING "VSOCK port number for logging traffic.") # RPM settings @@ -214,7 +216,7 @@ else() message(STATUS "Disable network trace interface since message queue is not supported") endif() -if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL) +if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL OR WITH_SYSTEMD_SOCKET_ACTIVATION) find_package(PkgConfig REQUIRED) execute_process(COMMAND pkg-config --modversion systemd OUTPUT_VARIABLE SYSTEMD_VERSION) string(REPLACE "\n" "" SYSTEMD_VERSION ${SYSTEMD_VERSION}) @@ -231,6 +233,13 @@ if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL) add_definitions(-DDLT_SYSTEMD_JOURNAL_ENABLE) endif() + if (WITH_SYSTEMD_SOCKET_ACTIVATION) + if(NOT DLT_IPC STREQUAL "UNIX_SOCKET") + message(FATAL_ERROR "WITH_SYSTEMD_SOCKET_ACTIVATION is only supported for UNIX_SOCKET") + endif() + add_definitions(-DDLT_SYSTEM_SOCKET_ACTIVATION_ENABLE) + endif() + set(systemd_SRCS ${PROJECT_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) set(SYSTEMD_UNITDIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system" CACHE PATH diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index e4e96bd..f7aaa26 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -61,6 +61,9 @@ endif(WITH_UDP_CONNECTION) add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) target_link_libraries(dlt-daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) +if (WITH_SYSTEMD_SOCKET_ACTIVATION) + target_link_libraries(dlt-daemon systemd) +endif() install(TARGETS dlt-daemon RUNTIME DESTINATION bin diff --git a/src/daemon/dlt_daemon_unix_socket.c b/src/daemon/dlt_daemon_unix_socket.c index ea889b0..4b9f472 100644 --- a/src/daemon/dlt_daemon_unix_socket.c +++ b/src/daemon/dlt_daemon_unix_socket.c @@ -38,6 +38,9 @@ #include #include #include +#if DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE +#include +#endif #include "dlt-daemon.h" #include "dlt_common.h" @@ -91,6 +94,48 @@ int dlt_daemon_unix_socket_open(int *sock, char *sock_path, int type, int mask) return -1; } +#ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE + + char **names = NULL; + const int num_fds = sd_listen_fds_with_names(0, &names); + bool sd_socket_open = false; + int i; + + if (num_fds <= 0) { + dlt_vlog(LOG_WARNING, "unix socket: no sockets configured via systemd, error: %s\n", strerror(errno)); + } else { + for (i = 0; i < num_fds; ++i) { + if (strcmp(sock_path, names[i]) != 0) { + continue; + } + + if (sd_is_socket_unix(i + SD_LISTEN_FDS_START, type, 1, names[i], strlen(names[i])) < 0) { + dlt_vlog(LOG_WARNING, + "unix socket: socket with matching name is not of correct type or not in listen mode, error: %s\n", + strerror(errno)); + continue; + } + + *sock = i + SD_LISTEN_FDS_START; + sd_socket_open = true; + dlt_vlog(LOG_INFO, "unix socket: sock_path %s found systemd socket %s\n", sock_path, names[i]); + break; + } + + /* + * The caller [of sd_listen_fds_with_names] needs to free the array + * itself and each of its elements with libc's free() call after use. + * */ + for (i = 0; i < num_fds; ++i) { + free(names[i]); + } + free(names); + } + + if (!sd_socket_open) { + dlt_vlog(LOG_INFO, "unix socket: sock_path %s no systemd socket found\n", sock_path); +#endif + if ((*sock = socket(AF_UNIX, type, 0)) == -1) { dlt_log(LOG_WARNING, "unix socket: socket() error"); return -1; @@ -118,6 +163,11 @@ int dlt_daemon_unix_socket_open(int *sock, char *sock_path, int type, int mask) /* restore permissions */ umask(old_mask); +#ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE + } // end of: if (!sd_socket_open) { +#endif + + return 0; } diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index 50e91d9..bfd4cd9 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -63,6 +63,12 @@ if(WITH_SYSTEMD) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-adaptor-udp.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_ADAPTOR_UDP) + if (WITH_SYSTEMD_SOCKET_ACTIVATION) + configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt.socket.cmake ${PROJECT_BINARY_DIR}/systemd/dlt.socket) + message( STATUS "Configured systemd socket file:dlt.socket" ) + install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt.socket DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) + endif() + message(STATUS "Unit files will be installed to ${SYSTEMD_CONFIGURATIONS_FILES_DIR} after make install" ) endif(WITH_SYSTEMD) diff --git a/systemd/dlt.socket.cmake b/systemd/dlt.socket.cmake new file mode 100755 index 0000000..9764c0f --- /dev/null +++ b/systemd/dlt.socket.cmake @@ -0,0 +1,8 @@ +[Socket] +ListenStream=@DLT_USER_IPC_PATH@/dlt +FileDescriptorName=@DLT_USER_IPC_PATH@/dlt +SocketGroup=dlt +SocketMode=0666 + +[Install] +WantedBy=sockets.target \ No newline at end of file -- cgit v1.2.1