From a30e4409a085a7a88516f9cc44485e8aa897652e Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Thu, 12 Jul 2018 13:27:42 +0800 Subject: [PATCH 01/18] Add functionality to notify systemd on olad startup and config reload This helps users who run olad under the management of systemd to order their services after olad startup, (i.e. starting up a daemon that depends on the olad RPC socket being available), avoiding the need for a manual delay. --- configure.ac | 7 +++++++ olad/OlaServer.cpp | 12 ++++++++++++ olad/Olad.cpp | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/configure.ac b/configure.ac index a447990294..2f22fa4f38 100644 --- a/configure.ac +++ b/configure.ac @@ -387,6 +387,13 @@ esac have_libftd2xx="no" AM_CONDITIONAL([HAVE_LIBFTD2XX], [test "x$have_libftd2xx" = xyes]) +# libsystemd +AC_SEARCH_LIBS([sd_notify], [systemd], [have_libsystemd="yes"]) +AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no"]) + +AS_IF([test "x$have_libsystemd" = xyes], + [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [define if libsystemd is installed])]) + # ncurses AC_CHECK_LIB([ncurses], [initscr], [have_ncurses="yes"]) AM_CONDITIONAL([HAVE_NCURSES], [test "x$have_ncurses" = xyes]) diff --git a/olad/OlaServer.cpp b/olad/OlaServer.cpp index 6d26f61815..ffd16c5a33 100644 --- a/olad/OlaServer.cpp +++ b/olad/OlaServer.cpp @@ -22,6 +22,10 @@ #include #endif // HAVE_CONFIG_H +#ifdef HAVE_LIBSYSTEMD +#include +#endif // HAVE_LIBSYSTEMD + #include #include #include @@ -472,9 +476,17 @@ bool OlaServer::InternalNewConnection( } void OlaServer::ReloadPluginsInternal() { +#ifdef HAVE_LIBSYSTEMD + // Return value is intentionally not checked for both calls. + // See return value section under sd_notify(3). + sd_notify(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); +#endif // HAVE_LIBSYSTEMD OLA_INFO << "Reloading plugins"; StopPlugins(); m_plugin_manager->LoadAll(); +#ifdef HAVE_LIBSYSTEMD + sd_notify(0, "READY=1\nSTATUS=Plugin reload complete\n"); +#endif // HAVE_LIBSYSTEMD } void OlaServer::UpdatePidStore(const RootPidStore *pid_store) { diff --git a/olad/Olad.cpp b/olad/Olad.cpp index 1a36b61c0d..ec0576edfd 100644 --- a/olad/Olad.cpp +++ b/olad/Olad.cpp @@ -24,6 +24,10 @@ #include #endif // HAVE_CONFIG_H +#if HAVE_LIBSYSTEMD +#include +#endif // HAVE_LIBSYSTEMD + #include #include #include @@ -171,6 +175,11 @@ int main(int argc, char *argv[]) { ola::NewCallback(olad->GetOlaServer(), &ola::OlaServer::ReloadPlugins)); #endif // _WIN32 +#if HAVE_LIBSYSTEMD + // Return value is intentionally not checked. See return value section + // under sd_notify(3). + sd_notify(0, "READY=1\nSTATUS=Startup complete\n"); +#endif // HAVE_LIBSYSTEMD olad->Run(); return ola::EXIT_OK; } From a5e57fe971e0a49f59bee5187923ef4bb5799894 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sat, 14 Jul 2018 15:20:59 +0800 Subject: [PATCH 02/18] Add systemd notification support to olad v2 Changes from v1: - Systemd support is now switched in via a flag to the configure script. - Failures to notify systemd are logged, but only when the notification socket is actually passed. - If the socket is not passed, a warning is displayed. - Added a utility library for the sd_notify calls. --- configure.ac | 22 ++++++++++++------ olad/Makefile.mk | 5 +++++ olad/NotifySystemd.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ olad/OlaServer.cpp | 14 +++++------- olad/Olad.cpp | 19 ++++++++++------ olad/Systemd.h | 46 +++++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 22 deletions(-) create mode 100644 olad/NotifySystemd.cpp create mode 100644 olad/Systemd.h diff --git a/configure.ac b/configure.ac index 2f22fa4f38..204a10d151 100644 --- a/configure.ac +++ b/configure.ac @@ -387,13 +387,6 @@ esac have_libftd2xx="no" AM_CONDITIONAL([HAVE_LIBFTD2XX], [test "x$have_libftd2xx" = xyes]) -# libsystemd -AC_SEARCH_LIBS([sd_notify], [systemd], [have_libsystemd="yes"]) -AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no"]) - -AS_IF([test "x$have_libsystemd" = xyes], - [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [define if libsystemd is installed])]) - # ncurses AC_CHECK_LIB([ncurses], [initscr], [have_ncurses="yes"]) AM_CONDITIONAL([HAVE_NCURSES], [test "x$have_ncurses" = xyes]) @@ -751,6 +744,21 @@ AC_ARG_ENABLE( [AS_HELP_STRING([--disable-doxygen-version], [Substitute the Doxygen version with latest, for the website])]) +# systemd support +AC_ARG_ENABLE( + [systemd], + [AS_HELP_STRING([--enable-systemd], [Enable systemd support])]) + +have_libsystemd="no" +AS_IF([test "x$enable_systemd" = "xyes"], + [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"]) + AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no"])]) + +AS_IF([test "x$have_libsystemd" = xyes], + [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [define if systemd support wanted])]) + +AM_CONDITIONAL([HAVE_LIBSYSTEMD], [test "x$have_libsystemd" = xyes]) + # UUCP Lock directory AC_ARG_WITH([uucp-lock], [AS_HELP_STRING([--with-uucp-lock], diff --git a/olad/Makefile.mk b/olad/Makefile.mk index 527bfc26c2..2585d95588 100644 --- a/olad/Makefile.mk +++ b/olad/Makefile.mk @@ -42,6 +42,11 @@ ola_server_sources += olad/HttpServerActions.cpp \ ola_server_additional_libs += common/http/libolahttp.la endif +if HAVE_LIBSYSTEMD +ola_server_sources += olad/NotifySystemd.cpp olad/Systemd.h +ola_server_additional_libs += $(libsystemd_LIBS) +endif + # lib olaserver lib_LTLIBRARIES += olad/libolaserver.la diff --git a/olad/NotifySystemd.cpp b/olad/NotifySystemd.cpp new file mode 100644 index 0000000000..e605ee8766 --- /dev/null +++ b/olad/NotifySystemd.cpp @@ -0,0 +1,51 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NotifySystemd.cpp + * Provides wrapped access to the systemd notification interface. + * Copyright (C) 2018 Shenghao Yang + */ + +#if HAVE_CONFIG_H +#include +#endif // HAVE_CONFIG_H + +#if HAVE_LIBSYSTEMD +#include +#include +#include +#endif // HAVE_LIBSYSTEMD + +#include "ola/Logging.h" + +#include "olad/Systemd.h" + +namespace ola { + +int notify_systemd(int unset_environment, const char *state) { + int rtn = sd_notify(unset_environment, state); + if (rtn < 0) { + char buf[1024]; + OLA_WARN << "Error sending notification to systemd: " << + strerror_r(-rtn, buf, sizeof(buf)); + } + return rtn; +} + +bool notify_available() { + return (sd_notify(0, "") != 0); +} + +} // namespace ola diff --git a/olad/OlaServer.cpp b/olad/OlaServer.cpp index ffd16c5a33..cb89fd0e6e 100644 --- a/olad/OlaServer.cpp +++ b/olad/OlaServer.cpp @@ -22,10 +22,6 @@ #include #endif // HAVE_CONFIG_H -#ifdef HAVE_LIBSYSTEMD -#include -#endif // HAVE_LIBSYSTEMD - #include #include #include @@ -67,6 +63,10 @@ #include "olad/OladHTTPServer.h" #endif // HAVE_LIBMICROHTTPD +#ifdef HAVE_LIBSYSTEMD +#include "olad/Systemd.h" +#endif // HAVE_LIBSYSTEMD + DEFINE_s_uint16(rpc_port, r, ola::OlaServer::DEFAULT_RPC_PORT, "The port to listen for RPCs on. Defaults to 9010."); DEFINE_default_bool(register_with_dns_sd, true, @@ -477,15 +477,13 @@ bool OlaServer::InternalNewConnection( void OlaServer::ReloadPluginsInternal() { #ifdef HAVE_LIBSYSTEMD - // Return value is intentionally not checked for both calls. - // See return value section under sd_notify(3). - sd_notify(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); + ola::notify_systemd(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); #endif // HAVE_LIBSYSTEMD OLA_INFO << "Reloading plugins"; StopPlugins(); m_plugin_manager->LoadAll(); #ifdef HAVE_LIBSYSTEMD - sd_notify(0, "READY=1\nSTATUS=Plugin reload complete\n"); + ola::notify_systemd(0, "READY=1\nSTATUS=Plugin reload complete\n"); #endif // HAVE_LIBSYSTEMD } diff --git a/olad/Olad.cpp b/olad/Olad.cpp index ec0576edfd..ab7c0ad6b9 100644 --- a/olad/Olad.cpp +++ b/olad/Olad.cpp @@ -24,10 +24,6 @@ #include #endif // HAVE_CONFIG_H -#if HAVE_LIBSYSTEMD -#include -#endif // HAVE_LIBSYSTEMD - #include #include #include @@ -40,6 +36,10 @@ // which needs to be after WinSock2.h, hence this order #include "olad/OlaDaemon.h" +#if HAVE_LIBSYSTEMD +#include "olad/Systemd.h" +#endif // HAVE_LIBSYSTEMD + #include "ola/Logging.h" #include "ola/base/Credentials.h" #include "ola/base/Flags.h" @@ -176,9 +176,14 @@ int main(int argc, char *argv[]) { #endif // _WIN32 #if HAVE_LIBSYSTEMD - // Return value is intentionally not checked. See return value section - // under sd_notify(3). - sd_notify(0, "READY=1\nSTATUS=Startup complete\n"); + if (ola::notify_available()) { + OLA_INFO << "Systemd notification socket present. Sending notifications."; + } else { + OLA_WARN << "Systemd notification socket not present"; + } + // Does not need to be guarded. sd_notify does its own internal check on + // the socket's presence, as well. + ola::notify_systemd(0, "READY=1\nSTATUS=Startup complete\n"); #endif // HAVE_LIBSYSTEMD olad->Run(); return ola::EXIT_OK; diff --git a/olad/Systemd.h b/olad/Systemd.h new file mode 100644 index 0000000000..ef6b98deca --- /dev/null +++ b/olad/Systemd.h @@ -0,0 +1,46 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Systemd.h + * Interface to systemd functionality. + * Copyright (C) 2018 Shenghao Yang + */ + +#ifndef OLAD_SYSTEMD_H_ +#define OLAD_SYSTEMD_H_ + +namespace ola { + +/* + * @brief Notify systemd about daemon state changes. + * + * This function logs on failures to queue notifications, but only if the + * notification socket environment variable is set. + * + * @param unset_environment whether to unset the notification socket environment + * variable so child processes cannot utilize it. + * @param state state block to pass to systemd. + * @return value returned from \ref sd_notify() + */ +int notify_systemd(int unset_environment, const char *state); + +/* + * @brief Tests whether the systemd notification socket is available. + * @return @code true if the socket is available, @code false if not. + */ +bool notify_available(); + +} // namespace ola +#endif // OLAD_SYSTEMD_H_ From 183ac8d43ab8719e5abbea4a4116f367ea3e821f Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sat, 14 Jul 2018 17:13:04 +0800 Subject: [PATCH 03/18] Fix license and doxygen warnings. - License error in both files, LGPL -> GPL - Wrong usage of @code in Systemd.h, should be @c --- olad/NotifySystemd.cpp | 20 ++++++++++---------- olad/Systemd.h | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/olad/NotifySystemd.cpp b/olad/NotifySystemd.cpp index e605ee8766..3e22a0fe8c 100644 --- a/olad/NotifySystemd.cpp +++ b/olad/NotifySystemd.cpp @@ -1,17 +1,17 @@ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * NotifySystemd.cpp * Provides wrapped access to the systemd notification interface. diff --git a/olad/Systemd.h b/olad/Systemd.h index ef6b98deca..0b013dc6ac 100644 --- a/olad/Systemd.h +++ b/olad/Systemd.h @@ -1,17 +1,17 @@ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Systemd.h * Interface to systemd functionality. @@ -38,7 +38,7 @@ int notify_systemd(int unset_environment, const char *state); /* * @brief Tests whether the systemd notification socket is available. - * @return @code true if the socket is available, @code false if not. + * @return @c true if the socket is available, @c false if not. */ bool notify_available(); From 50c9bdaee98db7deb789a98e342c947f929a9bc1 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Mon, 16 Jul 2018 12:59:01 +0800 Subject: [PATCH 04/18] Style fixups for commits to add systemd notification functionality - Scenarios in which HAVE_LIBSYSTEMD is defined is made clearer. - NotifySystemd.cpp and Systemd.h modified to match existing code style. - NotifySystemd.cpp renamed so header and implementation filenames match. - Call sites for functions declared in Systemd.h modified to use new names. --- configure.ac | 3 ++- olad/Makefile.mk | 2 +- olad/OlaServer.cpp | 4 ++-- olad/Olad.cpp | 4 ++-- olad/{NotifySystemd.cpp => Systemd.cpp} | 12 ++++++------ olad/Systemd.h | 8 ++++---- 6 files changed, 17 insertions(+), 16 deletions(-) rename olad/{NotifySystemd.cpp => Systemd.cpp} (80%) diff --git a/configure.ac b/configure.ac index 911bf74645..8f7a11f207 100644 --- a/configure.ac +++ b/configure.ac @@ -759,7 +759,8 @@ AS_IF([test "x$enable_systemd" = "xyes"], AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no"])]) AS_IF([test "x$have_libsystemd" = xyes], - [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [define if systemd support wanted])]) + [AC_DEFINE([HAVE_LIBSYSTEMD], [1], + [define if systemd support is wanted and libsystemd is present])]) AM_CONDITIONAL([HAVE_LIBSYSTEMD], [test "x$have_libsystemd" = xyes]) diff --git a/olad/Makefile.mk b/olad/Makefile.mk index 2585d95588..60c11bff28 100644 --- a/olad/Makefile.mk +++ b/olad/Makefile.mk @@ -43,7 +43,7 @@ ola_server_additional_libs += common/http/libolahttp.la endif if HAVE_LIBSYSTEMD -ola_server_sources += olad/NotifySystemd.cpp olad/Systemd.h +ola_server_sources += olad/Systemd.cpp olad/Systemd.h ola_server_additional_libs += $(libsystemd_LIBS) endif diff --git a/olad/OlaServer.cpp b/olad/OlaServer.cpp index cb89fd0e6e..292da5b392 100644 --- a/olad/OlaServer.cpp +++ b/olad/OlaServer.cpp @@ -477,13 +477,13 @@ bool OlaServer::InternalNewConnection( void OlaServer::ReloadPluginsInternal() { #ifdef HAVE_LIBSYSTEMD - ola::notify_systemd(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); + ola::NotifySystemd(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); #endif // HAVE_LIBSYSTEMD OLA_INFO << "Reloading plugins"; StopPlugins(); m_plugin_manager->LoadAll(); #ifdef HAVE_LIBSYSTEMD - ola::notify_systemd(0, "READY=1\nSTATUS=Plugin reload complete\n"); + ola::NotifySystemd(0, "READY=1\nSTATUS=Plugin reload complete\n"); #endif // HAVE_LIBSYSTEMD } diff --git a/olad/Olad.cpp b/olad/Olad.cpp index ab7c0ad6b9..6a4d140567 100644 --- a/olad/Olad.cpp +++ b/olad/Olad.cpp @@ -176,14 +176,14 @@ int main(int argc, char *argv[]) { #endif // _WIN32 #if HAVE_LIBSYSTEMD - if (ola::notify_available()) { + if (ola::NotifyAvailable()) { OLA_INFO << "Systemd notification socket present. Sending notifications."; } else { OLA_WARN << "Systemd notification socket not present"; } // Does not need to be guarded. sd_notify does its own internal check on // the socket's presence, as well. - ola::notify_systemd(0, "READY=1\nSTATUS=Startup complete\n"); + ola::NotifySystemd(0, "READY=1\nSTATUS=Startup complete\n"); #endif // HAVE_LIBSYSTEMD olad->Run(); return ola::EXIT_OK; diff --git a/olad/NotifySystemd.cpp b/olad/Systemd.cpp similarity index 80% rename from olad/NotifySystemd.cpp rename to olad/Systemd.cpp index 3e22a0fe8c..02aaaa98e3 100644 --- a/olad/NotifySystemd.cpp +++ b/olad/Systemd.cpp @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * NotifySystemd.cpp - * Provides wrapped access to the systemd notification interface. + * Systemd.cpp + * Provides wrapped access to systemd interfaces. * Copyright (C) 2018 Shenghao Yang */ @@ -34,17 +34,17 @@ namespace ola { -int notify_systemd(int unset_environment, const char *state) { +int NotifySystemd(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { char buf[1024]; - OLA_WARN << "Error sending notification to systemd: " << - strerror_r(-rtn, buf, sizeof(buf)); + OLA_WARN << "Error sending notification to systemd: " + << strerror_r(-rtn, buf, sizeof(buf)); } return rtn; } -bool notify_available() { +bool NotifyAvailable() { return (sd_notify(0, "") != 0); } diff --git a/olad/Systemd.h b/olad/Systemd.h index 0b013dc6ac..bedc543f09 100644 --- a/olad/Systemd.h +++ b/olad/Systemd.h @@ -26,21 +26,21 @@ namespace ola { /* * @brief Notify systemd about daemon state changes. * - * This function logs on failures to queue notifications, but only if the + * This function logs on any failure to queue notifications, but only if the * notification socket environment variable is set. * * @param unset_environment whether to unset the notification socket environment * variable so child processes cannot utilize it. * @param state state block to pass to systemd. - * @return value returned from \ref sd_notify() + * @return value returned from @ref sd_notify() */ -int notify_systemd(int unset_environment, const char *state); +int NotifySystemd(int unset_environment, const char *state); /* * @brief Tests whether the systemd notification socket is available. * @return @c true if the socket is available, @c false if not. */ -bool notify_available(); +bool NotifyAvailable(); } // namespace ola #endif // OLAD_SYSTEMD_H_ From 29556d07885db13fe971ed49d7b3be3c83cf683f Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Mon, 16 Jul 2018 14:04:07 +0800 Subject: [PATCH 05/18] Add additional checks and error messages when configuring for systemd - Added error messages to be output whenever dependent functionality / files are not present, to avoid silent failures. - Added additional check for strerror_r's presence to guard against ancient systems. --- configure.ac | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8f7a11f207..b5f1e4efd0 100644 --- a/configure.ac +++ b/configure.ac @@ -756,7 +756,11 @@ AC_ARG_ENABLE( have_libsystemd="no" AS_IF([test "x$enable_systemd" = "xyes"], [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"]) - AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no"])]) + AC_CHECK_HEADER([systemd/sd-daemon.h], [], + [have_libsystemd="no" + AC_MSG_ERROR([can't find systemd/sd-daemon.h necessary for systemd support])]) + AC_CHECK_FUNC([strerror_r], [], + [AC_MSG_ERROR([can't find strerror_r necessary for systemd support])])]) AS_IF([test "x$have_libsystemd" = xyes], [AC_DEFINE([HAVE_LIBSYSTEMD], [1], From b7afd380b0adf9764c5a1c507cedd1ac3fc587d0 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Wed, 25 Jul 2018 22:50:45 +0800 Subject: [PATCH 06/18] Style changes for function names and log messages - NotifySystemd() and NotifyAvailable() modified to better match the naming style of the functions provided by libsystemd. - Call sites modified to use new names. - Log messages emitted to inform the user about the presence of the notification socket has been changed to make it clear that systemd only provides the application with the address of the notification socket. Systemd does not have the process inherit a file descriptor to use when sending notifications. --- olad/OlaServer.cpp | 4 ++-- olad/Olad.cpp | 10 ++++++---- olad/Systemd.cpp | 4 ++-- olad/Systemd.h | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/olad/OlaServer.cpp b/olad/OlaServer.cpp index 292da5b392..58a5384d7b 100644 --- a/olad/OlaServer.cpp +++ b/olad/OlaServer.cpp @@ -477,13 +477,13 @@ bool OlaServer::InternalNewConnection( void OlaServer::ReloadPluginsInternal() { #ifdef HAVE_LIBSYSTEMD - ola::NotifySystemd(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); + ola::SystemdNotify(0, "RELOADING=1\nSTATUS=Reloading plugins\n"); #endif // HAVE_LIBSYSTEMD OLA_INFO << "Reloading plugins"; StopPlugins(); m_plugin_manager->LoadAll(); #ifdef HAVE_LIBSYSTEMD - ola::NotifySystemd(0, "READY=1\nSTATUS=Plugin reload complete\n"); + ola::SystemdNotify(0, "READY=1\nSTATUS=Plugin reload complete\n"); #endif // HAVE_LIBSYSTEMD } diff --git a/olad/Olad.cpp b/olad/Olad.cpp index 6a4d140567..e27705692a 100644 --- a/olad/Olad.cpp +++ b/olad/Olad.cpp @@ -176,14 +176,16 @@ int main(int argc, char *argv[]) { #endif // _WIN32 #if HAVE_LIBSYSTEMD - if (ola::NotifyAvailable()) { - OLA_INFO << "Systemd notification socket present. Sending notifications."; + if (ola::SystemdNotifyAvailable()) { + OLA_INFO << "Systemd notification socket address present. " + << "Sending notifications."; } else { - OLA_WARN << "Systemd notification socket not present"; + OLA_WARN << "Systemd notification socket address not present. " + << "Not sending notifications."; } // Does not need to be guarded. sd_notify does its own internal check on // the socket's presence, as well. - ola::NotifySystemd(0, "READY=1\nSTATUS=Startup complete\n"); + ola::SystemdNotify(0, "READY=1\nSTATUS=Startup complete\n"); #endif // HAVE_LIBSYSTEMD olad->Run(); return ola::EXIT_OK; diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index 02aaaa98e3..830b2ecead 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -34,7 +34,7 @@ namespace ola { -int NotifySystemd(int unset_environment, const char *state) { +int SystemdNotify(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { char buf[1024]; @@ -44,7 +44,7 @@ int NotifySystemd(int unset_environment, const char *state) { return rtn; } -bool NotifyAvailable() { +bool SystemdNotifyAvailable() { return (sd_notify(0, "") != 0); } diff --git a/olad/Systemd.h b/olad/Systemd.h index bedc543f09..81255219bb 100644 --- a/olad/Systemd.h +++ b/olad/Systemd.h @@ -34,13 +34,13 @@ namespace ola { * @param state state block to pass to systemd. * @return value returned from @ref sd_notify() */ -int NotifySystemd(int unset_environment, const char *state); +int SystemdNotify(int unset_environment, const char *state); /* * @brief Tests whether the systemd notification socket is available. * @return @c true if the socket is available, @c false if not. */ -bool NotifyAvailable(); +bool SystemdNotifyAvailable(); } // namespace ola #endif // OLAD_SYSTEMD_H_ From 83807d484ad4d66cc447a28ef395019fa13ff906 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Wed, 25 Jul 2018 23:13:33 +0800 Subject: [PATCH 07/18] Enable systemd support by default on supported build systems --- configure.ac | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b5f1e4efd0..35af363792 100644 --- a/configure.ac +++ b/configure.ac @@ -751,16 +751,17 @@ AC_ARG_ENABLE( # systemd support AC_ARG_ENABLE( [systemd], - [AS_HELP_STRING([--enable-systemd], [Enable systemd support])]) + [AS_HELP_STRING([--disable-systemd], [Disable systemd support])]) have_libsystemd="no" -AS_IF([test "x$enable_systemd" = "xyes"], +AS_IF([test "x$enable_systemd" != "xno"], [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"]) AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no" - AC_MSG_ERROR([can't find systemd/sd-daemon.h necessary for systemd support])]) + AC_MSG_WARN([disabling systemd support: can't find systemd/sd-daemon.h])]) AC_CHECK_FUNC([strerror_r], [], - [AC_MSG_ERROR([can't find strerror_r necessary for systemd support])])]) + [have_libsystemd="no" + AC_MSG_WARN([disabling systemd support: can't find strerror_r])])]) AS_IF([test "x$have_libsystemd" = xyes], [AC_DEFINE([HAVE_LIBSYSTEMD], [1], From 469361d2b1c52d0475621cb97653511fa7d60201 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Wed, 25 Jul 2018 23:24:10 +0800 Subject: [PATCH 08/18] Add comment clarifying usage of strerror_r - Most system functions return an integer value indicating success or failure, and the usage of strerror_r may seem that we are writing that value out to the log. - However, olad is compiled using GNU extensions, which means that the return value from strerror_r is a pointer to the description for the particular error value passed in. - This is a little bit unconventional, and the comment was added to clarify that this is only the case because of a non-standard GNU extension. --- olad/Systemd.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index 830b2ecead..3e0072853d 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -38,6 +38,10 @@ int SystemdNotify(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { char buf[1024]; + // olad is compiled under GNU extensions: the return value of + // strerror_r() is not an error code but a pointer to a character array + // containing the error description. The array returned is always NUL + // terminated, even in case of errors, so blindly using it is not a problem. OLA_WARN << "Error sending notification to systemd: " << strerror_r(-rtn, buf, sizeof(buf)); } From f15b385f536b2b18bf66bc0748ccd80b4209f7f5 Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Thu, 26 Jul 2018 00:11:04 +0800 Subject: [PATCH 09/18] Add a declaration for XSI-compliant strerror_r - This is to ensure that compilation will not be dependent on GNU extensions being enabled. - A new source file has to be added, because one cannot simply undef _GNU_SOURCE in Systemd.cpp - it will cause the a failure to compile - something in the logging framework depends on GNU extensions. --- configure.ac | 3 ++- olad/Makefile.mk | 3 ++- olad/Strerror_r.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++ olad/Strerror_r.h | 35 ++++++++++++++++++++++++++++++++ olad/Systemd.cpp | 15 +++++++------- 5 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 olad/Strerror_r.cpp create mode 100644 olad/Strerror_r.h diff --git a/configure.ac b/configure.ac index 35af363792..e576a248e2 100644 --- a/configure.ac +++ b/configure.ac @@ -755,7 +755,8 @@ AC_ARG_ENABLE( have_libsystemd="no" AS_IF([test "x$enable_systemd" != "xno"], - [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"]) + [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"], + [AC_MSG_WARN([disabling systemd support: can't find libsystemd])]) AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no" AC_MSG_WARN([disabling systemd support: can't find systemd/sd-daemon.h])]) diff --git a/olad/Makefile.mk b/olad/Makefile.mk index 60c11bff28..affd9ef8d7 100644 --- a/olad/Makefile.mk +++ b/olad/Makefile.mk @@ -43,7 +43,8 @@ ola_server_additional_libs += common/http/libolahttp.la endif if HAVE_LIBSYSTEMD -ola_server_sources += olad/Systemd.cpp olad/Systemd.h +ola_server_sources += olad/Strerror_r.cpp olad/Strerror_r.h \ + olad/Systemd.cpp olad/Systemd.h ola_server_additional_libs += $(libsystemd_LIBS) endif diff --git a/olad/Strerror_r.cpp b/olad/Strerror_r.cpp new file mode 100644 index 0000000000..962c686159 --- /dev/null +++ b/olad/Strerror_r.cpp @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Strerror_r.cpp + * Definition of strerror_r that is XSI-compliant. + * Copyright (C) 2018 Shenghao Yang + */ + +#if HAVE_CONFIG_H +#include +#endif // HAVE_CONFIG_H + +// Required for string.h to declare the standards-compliant version of +// strerror_r(), when compiling under glibc. Must come before the inclusion +// of string.h. +// These are conditional to avoid errors when not compiling with glibc, or +// when compiling with a compiler that does not define _POSIX_C_SOURCE. +#ifdef _GNU_SOURCE +#undef _GNU_SOURCE +#endif + +#ifdef _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#endif +#define _POSIX_C_SOURCE 200112L + +#include + +#include "olad/Strerror_r.h" + +namespace ola { + +int Strerror_r(int errnum, char* buf, size_t buflen) { + return strerror_r(errnum, buf, buflen); +} + +} // namespace ola diff --git a/olad/Strerror_r.h b/olad/Strerror_r.h new file mode 100644 index 0000000000..d259a4bebc --- /dev/null +++ b/olad/Strerror_r.h @@ -0,0 +1,35 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Strerror_r.h + * Declaration of strerror_r that is XSI-compliant. + * Copyright (C) 2018 Shenghao Yang + */ + +#ifndef OLAD_STRERROR_R_H_ +#define OLAD_STRERROR_R_H_ + +namespace ola { + +/* + * @brief XSI-compliant version of @ref strerror_r() + + * See strerror(3) for more details. + */ +int Strerror_r(int errnum, char* buf, size_t buflen); + +} // namespace ola + +#endif // OLAD_STRERROR_R_H_ diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index 3e0072853d..340f78c007 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -24,12 +24,11 @@ #if HAVE_LIBSYSTEMD #include -#include -#include #endif // HAVE_LIBSYSTEMD #include "ola/Logging.h" +#include "olad/Strerror_r.h" #include "olad/Systemd.h" namespace ola { @@ -38,12 +37,12 @@ int SystemdNotify(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { char buf[1024]; - // olad is compiled under GNU extensions: the return value of - // strerror_r() is not an error code but a pointer to a character array - // containing the error description. The array returned is always NUL - // terminated, even in case of errors, so blindly using it is not a problem. - OLA_WARN << "Error sending notification to systemd: " - << strerror_r(-rtn, buf, sizeof(buf)); + OLA_WARN << "Error sending notification to systemd: "; + if (ola::Strerror_r(-rtn, buf, sizeof(buf))) { + OLA_WARN << "errno = " << -rtn; + } else { + OLA_WARN << buf; + } } return rtn; } From d674930ed1c3a73c9533d32b9afe68a6c019622a Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sun, 29 Jul 2018 00:16:15 +0800 Subject: [PATCH 10/18] Fix formatting issues in log messages --- olad/Olad.cpp | 8 ++++---- olad/Systemd.cpp | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/olad/Olad.cpp b/olad/Olad.cpp index e27705692a..e154046051 100644 --- a/olad/Olad.cpp +++ b/olad/Olad.cpp @@ -177,11 +177,11 @@ int main(int argc, char *argv[]) { #if HAVE_LIBSYSTEMD if (ola::SystemdNotifyAvailable()) { - OLA_INFO << "Systemd notification socket address present. " - << "Sending notifications."; + OLA_INFO << "Systemd notification socket address present, " + << "sending notifications."; } else { - OLA_WARN << "Systemd notification socket address not present. " - << "Not sending notifications."; + OLA_WARN << "Systemd notification socket address not present, " + << "not sending notifications."; } // Does not need to be guarded. sd_notify does its own internal check on // the socket's presence, as well. diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index 340f78c007..f31245e7f3 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -37,11 +37,10 @@ int SystemdNotify(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { char buf[1024]; - OLA_WARN << "Error sending notification to systemd: "; if (ola::Strerror_r(-rtn, buf, sizeof(buf))) { - OLA_WARN << "errno = " << -rtn; + OLA_WARN << "Error sending notification to systemd: errno = " << -rtn; } else { - OLA_WARN << buf; + OLA_WARN << "Error sending notification to systemd: " << buf; } } return rtn; From bf8deff5d4c87b66787ee63f402f8d88de869cff Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sun, 29 Jul 2018 01:17:37 +0800 Subject: [PATCH 11/18] Move strerror_r wrapper into utility library - Strerorr_r wrapper could be useful to elements outside of olad --- common/base/Makefile.mk | 4 ++ {olad => common/base}/Strerror_r.cpp | 23 +++++------ configure.ac | 13 ++++--- include/ola/base/Makefile.mk | 4 ++ include/ola/base/Strerror_r.h | 57 ++++++++++++++++++++++++++++ olad/Makefile.mk | 3 +- olad/Strerror_r.h | 35 ----------------- olad/Systemd.cpp | 2 +- 8 files changed, 87 insertions(+), 54 deletions(-) rename {olad => common/base}/Strerror_r.cpp (60%) create mode 100644 include/ola/base/Strerror_r.h delete mode 100644 olad/Strerror_r.h diff --git a/common/base/Makefile.mk b/common/base/Makefile.mk index 758bbc356f..5844403575 100644 --- a/common/base/Makefile.mk +++ b/common/base/Makefile.mk @@ -9,6 +9,10 @@ common_libolacommon_la_SOURCES += \ common/base/SysExits.cpp \ common/base/Version.cpp +if HAVE_STRERROR_R +common_libolacommon_la_SOURCES += common/base/Strerror_r.cpp +endif + # TESTS ################################################## diff --git a/olad/Strerror_r.cpp b/common/base/Strerror_r.cpp similarity index 60% rename from olad/Strerror_r.cpp rename to common/base/Strerror_r.cpp index 962c686159..077f2b507e 100644 --- a/olad/Strerror_r.cpp +++ b/common/base/Strerror_r.cpp @@ -1,17 +1,17 @@ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Strerror_r.cpp * Definition of strerror_r that is XSI-compliant. @@ -27,6 +27,7 @@ // of string.h. // These are conditional to avoid errors when not compiling with glibc, or // when compiling with a compiler that does not define _POSIX_C_SOURCE. +// See strerror(3) as to why the macros are defined this way. #ifdef _GNU_SOURCE #undef _GNU_SOURCE #endif @@ -38,7 +39,7 @@ #include -#include "olad/Strerror_r.h" +#include "ola/base/Strerror_r.h" namespace ola { diff --git a/configure.ac b/configure.ac index e576a248e2..917a4b7728 100644 --- a/configure.ac +++ b/configure.ac @@ -184,8 +184,8 @@ AC_FUNC_CLOSEDIR_VOID AC_FUNC_VPRINTF AC_CHECK_FUNCS([bzero gettimeofday memmove memset mkdir strdup strrchr \ if_nametoindex inet_ntoa inet_ntop inet_aton inet_pton select \ - socket strerror getifaddrs getloadavg getpwnam_r getpwuid_r \ - getgrnam_r getgrgid_r secure_getenv]) + socket strerror strerror_r getifaddrs getloadavg getpwnam_r \ + getpwuid_r getgrnam_r getgrgid_r secure_getenv]) AC_MSG_CHECKING(for readdir_r deprecation) old_cxxflags=$CXXFLAGS @@ -228,6 +228,9 @@ AM_CONDITIONAL(HAVE_EPOLL, test "${ax_cv_have_epoll}" = "yes") AC_CHECK_FUNCS([kqueue]) AM_CONDITIONAL(HAVE_KQUEUE, test "${ac_cv_func_kqueue}" = "yes") +# strerror_r +AM_CONDITIONAL([HAVE_STRERROR_R], [test "x$ac_cv_func_strerror_r" = "xyes"]) + # check if the compiler supports -rdynamic AC_MSG_CHECKING(for -rdynamic support) old_cppflags=$CPPFLAGS @@ -760,9 +763,9 @@ AS_IF([test "x$enable_systemd" != "xno"], AC_CHECK_HEADER([systemd/sd-daemon.h], [], [have_libsystemd="no" AC_MSG_WARN([disabling systemd support: can't find systemd/sd-daemon.h])]) - AC_CHECK_FUNC([strerror_r], [], - [have_libsystemd="no" - AC_MSG_WARN([disabling systemd support: can't find strerror_r])])]) + AS_IF([test "x$ac_cv_func_strerror_r" = "xno"], + [have_libsystemd="no" + AC_MSG_WARN([disabling systemd support: can't find strerror_r])])]) AS_IF([test "x$have_libsystemd" = xyes], [AC_DEFINE([HAVE_LIBSYSTEMD], [1], diff --git a/include/ola/base/Makefile.mk b/include/ola/base/Makefile.mk index d1761cad27..24bb22830e 100644 --- a/include/ola/base/Makefile.mk +++ b/include/ola/base/Makefile.mk @@ -9,5 +9,9 @@ olabaseinclude_HEADERS = \ include/ola/base/Macro.h \ include/ola/base/SysExits.h +if HAVE_STRERROR_R +olabaseinclude_HEADERS += include/ola/base/Strerror_r.h +endif + nodist_olabaseinclude_HEADERS = \ include/ola/base/Version.h diff --git a/include/ola/base/Strerror_r.h b/include/ola/base/Strerror_r.h new file mode 100644 index 0000000000..98e39b2b1b --- /dev/null +++ b/include/ola/base/Strerror_r.h @@ -0,0 +1,57 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Strerror_r.h + * Declaration of strerror_r that is XSI-compliant. + * Copyright (C) 2018 Shenghao Yang + */ + +/** + * @defgroup strerror Description of system error codes + * @brief Error descriptions + * @details Some libraries provide their own version of functions to + * retrieve error descriptions that may not be compliant with + * adopted specifications. To work around that, we have a wrapper + * function that provides the standards-compliant interface at all times. + */ + +/** + * @addtogroup strerror + * @{ + * @file Strerror_r.h + * @} + */ + +#ifndef INCLUDE_OLA_BASE_STRERROR_R_H_ +#define INCLUDE_OLA_BASE_STRERROR_R_H_ + +namespace ola { + +/** + * @addtogroup strerror + * @{ + */ + +/* + * @brief XSI-compliant version of @ref strerror_r() + + * See strerror(3) for more details. + */ +int Strerror_r(int errnum, char* buf, size_t buflen); + +/**@}*/ +} // namespace ola + +#endif // INCLUDE_OLA_BASE_STRERROR_R_H_ diff --git a/olad/Makefile.mk b/olad/Makefile.mk index affd9ef8d7..60c11bff28 100644 --- a/olad/Makefile.mk +++ b/olad/Makefile.mk @@ -43,8 +43,7 @@ ola_server_additional_libs += common/http/libolahttp.la endif if HAVE_LIBSYSTEMD -ola_server_sources += olad/Strerror_r.cpp olad/Strerror_r.h \ - olad/Systemd.cpp olad/Systemd.h +ola_server_sources += olad/Systemd.cpp olad/Systemd.h ola_server_additional_libs += $(libsystemd_LIBS) endif diff --git a/olad/Strerror_r.h b/olad/Strerror_r.h deleted file mode 100644 index d259a4bebc..0000000000 --- a/olad/Strerror_r.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Strerror_r.h - * Declaration of strerror_r that is XSI-compliant. - * Copyright (C) 2018 Shenghao Yang - */ - -#ifndef OLAD_STRERROR_R_H_ -#define OLAD_STRERROR_R_H_ - -namespace ola { - -/* - * @brief XSI-compliant version of @ref strerror_r() - - * See strerror(3) for more details. - */ -int Strerror_r(int errnum, char* buf, size_t buflen); - -} // namespace ola - -#endif // OLAD_STRERROR_R_H_ diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index f31245e7f3..ab0ee43d1f 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -27,8 +27,8 @@ #endif // HAVE_LIBSYSTEMD #include "ola/Logging.h" +#include "ola/base/Strerror_r.h" -#include "olad/Strerror_r.h" #include "olad/Systemd.h" namespace ola { From 175b393662374db0cd487ee280c3dd32742eb80b Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Thu, 9 Aug 2018 22:16:19 +0800 Subject: [PATCH 12/18] Add new wrapper function for strerror_r and update naming - New wrapper function returns a C++ standard library string, that can be easily passed to one of the logging streams for output, as opposed to requiring the caller to discriminate, based on the return value, what to pass to the logging stream. - Added a constant that exposes the internal buffer size of the wrapper, in case this is required. - Naming for the wrapper functions and their source and header files have been changed to reflect convention. --- common/base/Makefile.mk | 3 +- common/base/StrError_R.cpp | 67 +++++++++++++++++++ .../{Strerror_r.cpp => StrError_R_XSI.cpp} | 11 +-- include/ola/base/Makefile.mk | 2 +- .../ola/base/{Strerror_r.h => StrError_R.h} | 43 +++++++++--- olad/Systemd.cpp | 10 +-- 6 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 common/base/StrError_R.cpp rename common/base/{Strerror_r.cpp => StrError_R_XSI.cpp} (81%) rename include/ola/base/{Strerror_r.h => StrError_R.h} (50%) diff --git a/common/base/Makefile.mk b/common/base/Makefile.mk index 5844403575..73d8473cde 100644 --- a/common/base/Makefile.mk +++ b/common/base/Makefile.mk @@ -10,7 +10,8 @@ common_libolacommon_la_SOURCES += \ common/base/Version.cpp if HAVE_STRERROR_R -common_libolacommon_la_SOURCES += common/base/Strerror_r.cpp +common_libolacommon_la_SOURCES += common/base/StrError_R.cpp \ + common/base/StrError_R_XSI.cpp endif # TESTS diff --git a/common/base/StrError_R.cpp b/common/base/StrError_R.cpp new file mode 100644 index 0000000000..8f3218de68 --- /dev/null +++ b/common/base/StrError_R.cpp @@ -0,0 +1,67 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * StrError_R.cpp + * Helper function for StrError_R_XSI(). + * Copyright (C) 2018 Shenghao Yang + */ + +#if HAVE_CONFIG_H +#include +#endif // HAVE_CONFIG_H + +#include +#include + +#include +#include + +#include "ola/base/StrError_R.h" + +namespace ola { + +const int StrError_R_BufSize(1024); + +std::string StrError_R(int errnum) { + // Pre-allocate to prevent re-allocation. + std::string out(StrError_R_BufSize, ' '); + out.assign("errno = "); + + // Buffer size here is digits10 + 3 to account for: + // - Systems in which the int type cannot represent the full range of base 10 + // digits in the position of the most significant base 10 digit. + // - Terminating NUL byte added by snprintf. + // - 1 additional unit of storage just in case something absurd is used + // on the host system (negative errno / zero-width int type, anyone? - + // though this is meant to be impossible). + char errs[std::numeric_limits::digits10 + 3]; + if (static_cast(snprintf(errs, sizeof(errs), "%d", errnum)) + >= sizeof(errs)) { + out.append(""); + } else { + out.append(errs); + } + const std::string::size_type olen(out.size()); + + out.resize(StrError_R_BufSize, ' '); + if (StrError_R_XSI(errnum, &(out[0]), out.size())) { + out.resize(olen); + } else { + out.resize(strlen(&(out[0]))); + } + return out; +} + +} // namespace ola diff --git a/common/base/Strerror_r.cpp b/common/base/StrError_R_XSI.cpp similarity index 81% rename from common/base/Strerror_r.cpp rename to common/base/StrError_R_XSI.cpp index 077f2b507e..22c6928e26 100644 --- a/common/base/Strerror_r.cpp +++ b/common/base/StrError_R_XSI.cpp @@ -13,8 +13,11 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * Strerror_r.cpp - * Definition of strerror_r that is XSI-compliant. + * StrError_R_XSI.cpp + * Definition of strerror_r() that is XSI-compliant. + * This extra file is required because the header declaring the symbols + * for the C++ string library conflicts with the macros used to expose + * the XSI-compliant declaration of strerror_r(). * Copyright (C) 2018 Shenghao Yang */ @@ -39,11 +42,9 @@ #include -#include "ola/base/Strerror_r.h" - namespace ola { -int Strerror_r(int errnum, char* buf, size_t buflen) { +int StrError_R_XSI(int errnum, char* buf, size_t buflen) { return strerror_r(errnum, buf, buflen); } diff --git a/include/ola/base/Makefile.mk b/include/ola/base/Makefile.mk index 24bb22830e..5811120207 100644 --- a/include/ola/base/Makefile.mk +++ b/include/ola/base/Makefile.mk @@ -10,7 +10,7 @@ olabaseinclude_HEADERS = \ include/ola/base/SysExits.h if HAVE_STRERROR_R -olabaseinclude_HEADERS += include/ola/base/Strerror_r.h +olabaseinclude_HEADERS += include/ola/base/StrError_R.h endif nodist_olabaseinclude_HEADERS = \ diff --git a/include/ola/base/Strerror_r.h b/include/ola/base/StrError_R.h similarity index 50% rename from include/ola/base/Strerror_r.h rename to include/ola/base/StrError_R.h index 98e39b2b1b..fcdd28bd5e 100644 --- a/include/ola/base/Strerror_r.h +++ b/include/ola/base/StrError_R.h @@ -13,30 +13,31 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * Strerror_r.h - * Declaration of strerror_r that is XSI-compliant. + * StrError_R.h + * Helper functions for strerror_r and a declaration of strerror_r that is + * XSI-compliant. * Copyright (C) 2018 Shenghao Yang */ /** * @defgroup strerror Description of system error codes * @brief Error descriptions - * @details Some libraries provide their own version of functions to - * retrieve error descriptions that may not be compliant with - * adopted specifications. To work around that, we have a wrapper - * function that provides the standards-compliant interface at all times. + * @details Convenience functions to obtain descriptions of system error codes. + * The functions in this group are only defined if @ref strerror_r() is available. */ /** * @addtogroup strerror * @{ - * @file Strerror_r.h + * @file StrError_R.h * @} */ #ifndef INCLUDE_OLA_BASE_STRERROR_R_H_ #define INCLUDE_OLA_BASE_STRERROR_R_H_ +#include + namespace ola { /** @@ -44,12 +45,32 @@ namespace ola { * @{ */ -/* +/** + * @brief Length of the internal buffer used for @ref StrError_R(). + * + * If the length of the system-provided error description exceeds the length + * of this buffer minus one, then the output of @ref StrError_R() will only + * include the numerical error value provided. + */ +extern const int StrError_R_BufSize; + +/** * @brief XSI-compliant version of @ref strerror_r() - - * See strerror(3) for more details. + * + * See https://linux.die.net/man/3/strerror for more details. + */ +int StrError_R_XSI(int errnum, char* buf, size_t buflen); + +/** + * @brief Convenience function that wraps @ref StrError_R_XSI(). + * + * @param errnum error value to generate the textual description for. + * @return Textual description of the error value. If the description is + * trucnated due to an insufficient buffer length, the description will + * be in the form: "errno = errnum". + * @sa StrError_R_BufSize for information regarding truncation. */ -int Strerror_r(int errnum, char* buf, size_t buflen); +std::string StrError_R(int errnum); /**@}*/ } // namespace ola diff --git a/olad/Systemd.cpp b/olad/Systemd.cpp index ab0ee43d1f..93a85cc007 100644 --- a/olad/Systemd.cpp +++ b/olad/Systemd.cpp @@ -27,7 +27,7 @@ #endif // HAVE_LIBSYSTEMD #include "ola/Logging.h" -#include "ola/base/Strerror_r.h" +#include "ola/base/StrError_R.h" #include "olad/Systemd.h" @@ -36,12 +36,8 @@ namespace ola { int SystemdNotify(int unset_environment, const char *state) { int rtn = sd_notify(unset_environment, state); if (rtn < 0) { - char buf[1024]; - if (ola::Strerror_r(-rtn, buf, sizeof(buf))) { - OLA_WARN << "Error sending notification to systemd: errno = " << -rtn; - } else { - OLA_WARN << "Error sending notification to systemd: " << buf; - } + OLA_WARN << "Error sending notification to systemd: " + << ola::StrError_R(-rtn); } return rtn; } From 1cd1202def6f58104e3014d4803c0e0be51b6fac Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Fri, 10 Aug 2018 14:54:26 +0800 Subject: [PATCH 13/18] Refactor StrError_R() and fix doxygen references. - In StrError_R(): Assume the happy path where the buffer is sufficient to hold the error message, first, instead of preemptively filling the buffer with the fallback numerical code. We rely on the fallback behaviour only when the buffer has been deemed to be too small. - In StrError_R(): Properly handle negative return values from snprintf(), instead of casting it away without considering the possibility of the value being negative. - Doxygen: generation of documentation produced warnings due to linking against strerror_r(), a symbol that wasn't found by doxygen because string.h wasn't included in StrError_R.h used to generate doc output. Including it wasn't necessary, so the references were dropped and fixed-width text is used to refer to the function instead. --- common/base/StrError_R.cpp | 43 ++++++++++++++++++----------------- include/ola/base/StrError_R.h | 4 ++-- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/common/base/StrError_R.cpp b/common/base/StrError_R.cpp index 8f3218de68..107ed142ea 100644 --- a/common/base/StrError_R.cpp +++ b/common/base/StrError_R.cpp @@ -36,28 +36,29 @@ const int StrError_R_BufSize(1024); std::string StrError_R(int errnum) { // Pre-allocate to prevent re-allocation. - std::string out(StrError_R_BufSize, ' '); - out.assign("errno = "); - - // Buffer size here is digits10 + 3 to account for: - // - Systems in which the int type cannot represent the full range of base 10 - // digits in the position of the most significant base 10 digit. - // - Terminating NUL byte added by snprintf. - // - 1 additional unit of storage just in case something absurd is used - // on the host system (negative errno / zero-width int type, anyone? - - // though this is meant to be impossible). - char errs[std::numeric_limits::digits10 + 3]; - if (static_cast(snprintf(errs, sizeof(errs), "%d", errnum)) - >= sizeof(errs)) { - out.append(""); - } else { - out.append(errs); - } - const std::string::size_type olen(out.size()); - - out.resize(StrError_R_BufSize, ' '); + std::string out(StrError_R_BufSize, '\0'); if (StrError_R_XSI(errnum, &(out[0]), out.size())) { - out.resize(olen); + out.assign("errno = "); + // Buffer size here is digits10 + 3 to account for: + // - Systems in which the int type cannot represent the full range + // of digits in the position of the most significant base 10 digit. + // (i.e. 0-2 representable in an 8-bit unsigned integer at the + // hundredth's place instead of 0-9 because an u8 is clamped to + // [0, 255]) + // - Terminating NUL byte added by snprintf. + // - 1 additional unit of storage just in case a negative errnum is + // passed, and somehow StrError_R_XSI() failed on that. + char errs[std::numeric_limits::digits10 + 3]; + int r(snprintf(errs, sizeof(errs), "%d", errnum)); + if (r < 0) { + out.append(""); + // Ugly cast required to avoid compiler warning when comparing + // numbers of different signedness. + } else if (static_cast(r) >= sizeof(errs)) { + out.append(""); + } else { + out.append(errs); + } } else { out.resize(strlen(&(out[0]))); } diff --git a/include/ola/base/StrError_R.h b/include/ola/base/StrError_R.h index fcdd28bd5e..30eb0c7147 100644 --- a/include/ola/base/StrError_R.h +++ b/include/ola/base/StrError_R.h @@ -23,7 +23,7 @@ * @defgroup strerror Description of system error codes * @brief Error descriptions * @details Convenience functions to obtain descriptions of system error codes. - * The functions in this group are only defined if @ref strerror_r() is available. + * The functions in this group are only defined if \c strerror_r() is available. */ /** @@ -55,7 +55,7 @@ namespace ola { extern const int StrError_R_BufSize; /** - * @brief XSI-compliant version of @ref strerror_r() + * @brief XSI-compliant version of \c strerror_r() * * See https://linux.die.net/man/3/strerror for more details. */ From d62a8f614507205e44fcf334980eb40dff1325cf Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sun, 12 Aug 2018 18:40:23 +0800 Subject: [PATCH 14/18] Fix formatting, style, and spelling, refactor StrError_R - Formatting, style, and spelling: - Fixes for wrong spelling in StrError_R.h - Documentation special command used to refer to manual page for strerror_r() instead of merely mentioning the URL for the manual page. - Style changes to initializers for variables defined in StrError_R.cpp, in order to match conventions. - Refactored StrError_R: - Switched to using ostringstream to convert error value to a human-readable number, avoiding complex error handling at the cost of longer execution time, but this path should not be taken for the most part, so any effect should be minimal. --- common/base/StrError_R.cpp | 26 ++++++-------------------- include/ola/base/StrError_R.h | 9 +++++---- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/common/base/StrError_R.cpp b/common/base/StrError_R.cpp index 107ed142ea..5501469af8 100644 --- a/common/base/StrError_R.cpp +++ b/common/base/StrError_R.cpp @@ -27,37 +27,23 @@ #include #include +#include #include "ola/base/StrError_R.h" namespace ola { -const int StrError_R_BufSize(1024); +const int StrError_R_BufSize = 1024; std::string StrError_R(int errnum) { // Pre-allocate to prevent re-allocation. std::string out(StrError_R_BufSize, '\0'); if (StrError_R_XSI(errnum, &(out[0]), out.size())) { - out.assign("errno = "); - // Buffer size here is digits10 + 3 to account for: - // - Systems in which the int type cannot represent the full range - // of digits in the position of the most significant base 10 digit. - // (i.e. 0-2 representable in an 8-bit unsigned integer at the - // hundredth's place instead of 0-9 because an u8 is clamped to - // [0, 255]) - // - Terminating NUL byte added by snprintf. - // - 1 additional unit of storage just in case a negative errnum is - // passed, and somehow StrError_R_XSI() failed on that. - char errs[std::numeric_limits::digits10 + 3]; - int r(snprintf(errs, sizeof(errs), "%d", errnum)); - if (r < 0) { - out.append(""); - // Ugly cast required to avoid compiler warning when comparing - // numbers of different signedness. - } else if (static_cast(r) >= sizeof(errs)) { - out.append(""); + std::ostringstream errs("errno = "); + if (!(errs << errnum)) { + out.assign("errno = "); } else { - out.append(errs); + out.assign(errs.str()); } } else { out.resize(strlen(&(out[0]))); diff --git a/include/ola/base/StrError_R.h b/include/ola/base/StrError_R.h index 30eb0c7147..5bd1f6719e 100644 --- a/include/ola/base/StrError_R.h +++ b/include/ola/base/StrError_R.h @@ -23,7 +23,8 @@ * @defgroup strerror Description of system error codes * @brief Error descriptions * @details Convenience functions to obtain descriptions of system error codes. - * The functions in this group are only defined if \c strerror_r() is available. + * The functions and variables in this group are only defined if \c strerror_r() + * is available. */ /** @@ -55,9 +56,9 @@ namespace ola { extern const int StrError_R_BufSize; /** - * @brief XSI-compliant version of \c strerror_r() + * @brief XSI-compliant version of \c strerror_r(). * - * See https://linux.die.net/man/3/strerror for more details. + * @see https://linux.die.net/man/3/strerror for more details. */ int StrError_R_XSI(int errnum, char* buf, size_t buflen); @@ -66,7 +67,7 @@ int StrError_R_XSI(int errnum, char* buf, size_t buflen); * * @param errnum error value to generate the textual description for. * @return Textual description of the error value. If the description is - * trucnated due to an insufficient buffer length, the description will + * truncated due to an insufficient buffer length, the description will * be in the form: "errno = errnum". * @sa StrError_R_BufSize for information regarding truncation. */ From ff347243aa956a2981785429cd529e6684a8fa0e Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sun, 12 Aug 2018 18:43:56 +0800 Subject: [PATCH 15/18] Add config error on being unable to explicitly enable systemd support - Configure script will now check if systemd support has been explicitly enabled when it is unable to enable it. - Provides user feedback when his explicit choice fails, instead of failing silently with a warning message that is probably hidden in the mountain of messages the configure script generates. --- configure.ac | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 917a4b7728..b1341b723e 100644 --- a/configure.ac +++ b/configure.ac @@ -757,14 +757,14 @@ AC_ARG_ENABLE( [AS_HELP_STRING([--disable-systemd], [Disable systemd support])]) have_libsystemd="no" -AS_IF([test "x$enable_systemd" != "xno"], - [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd="yes"], +AS_IF([test "x$enable_systemd" != xno], + [PKG_CHECK_MODULES([libsystemd], [libsystemd >= 38], [have_libsystemd=yes], [AC_MSG_WARN([disabling systemd support: can't find libsystemd])]) AC_CHECK_HEADER([systemd/sd-daemon.h], [], - [have_libsystemd="no" + [have_libsystemd=no AC_MSG_WARN([disabling systemd support: can't find systemd/sd-daemon.h])]) - AS_IF([test "x$ac_cv_func_strerror_r" = "xno"], - [have_libsystemd="no" + AS_IF([test "x$ac_cv_func_strerror_r" = xno], + [have_libsystemd=no AC_MSG_WARN([disabling systemd support: can't find strerror_r])])]) AS_IF([test "x$have_libsystemd" = xyes], @@ -773,6 +773,9 @@ AS_IF([test "x$have_libsystemd" = xyes], AM_CONDITIONAL([HAVE_LIBSYSTEMD], [test "x$have_libsystemd" = xyes]) +AS_IF([test "x$enable_systemd" = xyes && test "x$have_libsystemd" = xno], + [AC_MSG_ERROR([could not enable systemd support])]) + # UUCP Lock directory AC_ARG_WITH([uucp-lock], [AS_HELP_STRING([--with-uucp-lock], From f6f5813e07d1c508092e09b6603c4d8ef7440a1f Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sun, 12 Aug 2018 21:02:13 +0800 Subject: [PATCH 16/18] Switch to internal ola library function for int to string conversion --- common/base/StrError_R.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/common/base/StrError_R.cpp b/common/base/StrError_R.cpp index 5501469af8..b28153938d 100644 --- a/common/base/StrError_R.cpp +++ b/common/base/StrError_R.cpp @@ -30,6 +30,7 @@ #include #include "ola/base/StrError_R.h" +#include "ola/strings/Format.h" namespace ola { @@ -39,12 +40,7 @@ std::string StrError_R(int errnum) { // Pre-allocate to prevent re-allocation. std::string out(StrError_R_BufSize, '\0'); if (StrError_R_XSI(errnum, &(out[0]), out.size())) { - std::ostringstream errs("errno = "); - if (!(errs << errnum)) { - out.assign("errno = "); - } else { - out.assign(errs.str()); - } + out.assign(std::string("errno = ") + ola::strings::IntToString(errnum)); } else { out.resize(strlen(&(out[0]))); } From a21f0a4ad7ac844a4e5ba6f2c3c800a20755f8ef Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Sat, 25 Aug 2018 19:40:41 +0800 Subject: [PATCH 17/18] Add systemd unit file for running olad with systemd in user mode Since most items are tagged using "uaccess", this is the most easy way to run the olad daemon, without creating additional system users. Note that DynamicUsers can be used in future along with a SupplementaryGroups=plugdev in order to implement an olad service that can be spawned off the main systemd process in charge of the whole system. Since this option is not supported in 232, that has not been enabled here. --- systemd/olad.service | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 systemd/olad.service diff --git a/systemd/olad.service b/systemd/olad.service new file mode 100644 index 0000000000..07c6277a7f --- /dev/null +++ b/systemd/olad.service @@ -0,0 +1,30 @@ +[Unit] +Description=Ola Daemon (User mode) +Documentation=https://github.com/OpenLightingProject/ola + +[Service] +# Task control options +Type=notify +ExecStart=/usr/bin/olad +ExecReload=/usr/bin/kill -HUP $MAINPID +NotifyAccess=main +Restart=on-failure + +# Exec Options +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=tmpfs +ProtectControlGroups=true +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +RestrictNamespaces=true +LockPersonality=true +MemoryDenyWriteExecute=true +SystemCallArchitectures=native + +# Directory specifications +ConfigurationDirectory="~/.ola/" +WorkingDirectory=~ + +[Install] +WantedBy=default.target + From c714ee8357f9bf2eebd6a4420123f27138877faf Mon Sep 17 00:00:00 2001 From: Shenghao Yang Date: Tue, 11 Sep 2018 00:12:46 +0800 Subject: [PATCH 18/18] Add more documentation URLs to the unit file for the user instance. --- systemd/olad.service | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/systemd/olad.service b/systemd/olad.service index 07c6277a7f..0a09d6283f 100644 --- a/systemd/olad.service +++ b/systemd/olad.service @@ -1,5 +1,7 @@ [Unit] -Description=Ola Daemon (User mode) +Description=Ola Daemon (User instance) +Documentation=https://docs.openlighting.org/ola/conf/ +Documentation=https://www.openlighting.org/ola/ Documentation=https://github.com/OpenLightingProject/ola [Service]