Move io context to singleton
The way we pass around io contexts is somewhat odd. Boost maintainers
in slack recommended that we just have a method that returns an io
context, and from there we can control this (context link lost years
ago).
The new version of clang claims the singleton pattern of passing in an
io_context pattern is a potential nullptr dereference. It's technically
correct, as calling the singleton without immediately initializing the
io context will lead to a crash.
This commit implements what the boost maintainers suggested, having a
single method that returns "the context" that should be used. This also
helps to maintain isolation, as some pieces are no longer tied directly
to dbus to get their reactor.
Tested: WIP
Change-Id: Ifaa11335ae00a3d092ecfdfb26a38380227e8576
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/http/app.hpp b/http/app.hpp
index f982618..f8d4d97 100644
--- a/http/app.hpp
+++ b/http/app.hpp
@@ -7,6 +7,7 @@
#include "async_resp.hpp"
#include "http_request.hpp"
#include "http_server.hpp"
+#include "io_context_singleton.hpp"
#include "logging.hpp"
#include "routing.hpp"
#include "routing/dynamicrule.hpp"
@@ -14,7 +15,6 @@
#include <sys/socket.h>
#include <systemd/sd-daemon.h>
-#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/context.hpp>
@@ -44,11 +44,6 @@
raw_socket_t, ssl_socket_t>;
using server_type = Server<App, socket_type>;
- explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
- std::make_shared<boost::asio::io_context>()) :
- io(std::move(ioIn))
- {}
-
template <typename Adaptor>
void handleUpgrade(const std::shared_ptr<Request>& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -89,13 +84,8 @@
server->loadCertificate();
}
- std::optional<boost::asio::ip::tcp::acceptor> setupSocket()
+ static std::optional<boost::asio::ip::tcp::acceptor> setupSocket()
{
- if (io == nullptr)
- {
- BMCWEB_LOG_CRITICAL("IO was nullptr?");
- return std::nullopt;
- }
constexpr int defaultPort = 18080;
if (sd_listen_fds(0) == 1)
{
@@ -106,7 +96,8 @@
BMCWEB_LOG_INFO("Starting webserver on socket handle {}",
SD_LISTEN_FDS_START);
return boost::asio::ip::tcp::acceptor(
- *io, boost::asio::ip::tcp::v6(), SD_LISTEN_FDS_START);
+ getIoContext(), boost::asio::ip::tcp::v6(),
+ SD_LISTEN_FDS_START);
}
BMCWEB_LOG_ERROR(
"bad incoming socket, starting webserver on port {}",
@@ -114,8 +105,9 @@
}
BMCWEB_LOG_INFO("Starting webserver on port {}", defaultPort);
return boost::asio::ip::tcp::acceptor(
- *io, boost::asio::ip::tcp::endpoint(
- boost::asio::ip::make_address("0.0.0.0"), defaultPort));
+ getIoContext(),
+ boost::asio::ip::tcp::endpoint(
+ boost::asio::ip::make_address("0.0.0.0"), defaultPort));
}
void run()
@@ -128,7 +120,7 @@
BMCWEB_LOG_CRITICAL("Couldn't start server");
return;
}
- server.emplace(this, std::move(*acceptor), sslContext, io);
+ server.emplace(this, std::move(*acceptor), sslContext, getIoContext());
server->run();
}
@@ -158,14 +150,6 @@
std::shared_ptr<boost::asio::ssl::context> sslContext = nullptr;
- boost::asio::io_context& ioContext()
- {
- return *io;
- }
-
- private:
- std::shared_ptr<boost::asio::io_context> io;
-
std::optional<server_type> server;
Router router;