daemons: Move sdbus++ event loop handling
We are going to introduce multiple daemons in the velia project soon.
All the daemons will (so far) talk/listen to D-Bus using sdbus++ [1]
library. This library also support a basic event loop which we are
using and the parts that initialize the event loop are going to be
common among those daemons.
Therefore this patch factors out the event loop initialization and
operations into a separate header so that future daemons can use it too
without too much code duplication.
Also, originally the event loop std::thread object was constructed
inside the main() function. However, to simplify things, this patch
constructs the thread object as a global variable. We are using other
global variables anyway (sdbus++ D-Bus connection object), so we can
declare both these variables at once and the event loop code becomes
less scattered around the file.
[1] https://github.com/Kistler-Group/sdbus-cpp/
Change-Id: I9de64a9cbf8ddb347ef0a65efdce26ac3a230004
diff --git a/src/main.cpp b/src/main.cpp
index c0128df..b264da1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,3 @@
-#include <csignal>
#include <docopt.h>
#include <future>
#include <sdbus-c++/sdbus-c++.h>
@@ -11,6 +10,7 @@
#include "health/manager/StateManager.h"
#include "health/outputs/callables.h"
#include "ietf-hardware/sysrepo/Sysrepo.h"
+#include "main.h"
#include "system/Sysrepo.h"
#include "utils/exceptions.h"
#include "utils/journal.h"
@@ -60,7 +60,7 @@
--systemd-ignore-unit=<Unit> Ignore state of systemd's unit in systemd state tracker. Can be specified multiple times.
)";
-std::unique_ptr<sdbus::IConnection> g_dbusConnection;
+DBUS_EVENTLOOP_INIT
int main(int argc, char* argv[])
{
@@ -76,16 +76,11 @@
velia::utils::initLogs(loggingSink);
spdlog::set_level(spdlog::level::info);
- std::thread eventLoop;
-
try {
spdlog::set_level(parseLogLevel("Generic", args["--log-level"]));
spdlog::get("hardware")->set_level(parseLogLevel("Hardware loggers", args["--hardware-log-level"]));
spdlog::get("sysrepo")->set_level(parseLogLevel("Sysrepo library", args["--sysrepo-log-level"]));
- spdlog::get("main")->debug("Opening DBus connection");
- g_dbusConnection = sdbus::createSystemBusConnection();
-
spdlog::get("main")->debug("Opening Sysrepo connection");
auto srConn = std::make_shared<sysrepo::Connection>();
auto srSess = std::make_shared<sysrepo::Session>(srConn);
@@ -107,15 +102,7 @@
spdlog::get("main")->debug("Initializing Sysrepo for system models");
auto sysrepoSystem = velia::system::Sysrepo(srSess, "/etc/os-release");
- // Gracefully leave dbus event loop on SIGTERM
- struct sigaction sigact;
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = [](int) { g_dbusConnection->leaveEventLoop(); }; // sdbus-c++'s implementation doesn't mind if called before entering the event loop. It simply leaves the loop on entry
- sigact.sa_flags = SA_SIGINFO;
- sigaction(SIGTERM, &sigact, nullptr);
-
- spdlog::get("main")->debug("Starting DBus event loop");
- eventLoop = std::thread([] { g_dbusConnection->enterEventLoop(); });
+ DBUS_EVENTLOOP_START
// health
auto manager = std::make_shared<velia::health::StateManager>();
@@ -138,9 +125,8 @@
spdlog::get("main")->debug("All inputs initialized.");
- eventLoop.join();
+ DBUS_EVENTLOOP_END;
- spdlog::get("main")->debug("Shutting down");
return 0;
} catch (std::exception& e) {
velia::utils::fatalException(spdlog::get("main"), e, "main");
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..7c60acb
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <csignal>
+#include <sdbus-c++/sdbus-c++.h>
+#include <thread>
+#include "utils/log.h"
+
+#define DBUS_EVENTLOOP_INIT \
+ std::unique_ptr<sdbus::IConnection> g_dbusConnection; \
+ std::thread g_eventLoop;
+
+#define DBUS_EVENTLOOP_START \
+ spdlog::get("main")->debug("Opening DBus connection"); \
+ g_dbusConnection = sdbus::createSystemBusConnection(); \
+ /* Gracefully leave dbus event loop on SIGTERM */ \
+ struct sigaction sigact; \
+ memset(&sigact, 0, sizeof(sigact)); \
+ /* sdbus-c++'s implementation doesn't mind if called before entering the event loop. It simply leaves the loop on entry */ \
+ sigact.sa_flags = SA_SIGINFO; \
+ sigact.sa_handler = [](int) { g_dbusConnection->leaveEventLoop(); }; \
+ sigaction(SIGTERM, &sigact, nullptr); \
+ spdlog::get("main")->debug("Starting DBus event loop"); \
+ g_eventLoop = std::thread([] { g_dbusConnection->enterEventLoop(); }); \
+
+#define DBUS_EVENTLOOP_END \
+ g_eventLoop.join(); \
+ spdlog::get("main")->debug("Shutting down");