entity-manager: remove global io_context

Remove the global var
```
boost::asio::io_context io
```
and move it to be a local var in the main function.

Since boost::asio::io_context io is declared first, it in scope for the
entire program duration and should not cause any issues from that
perspective.

The io_context is passed through where needed. In case there is a class
already defined, the class now has a reference to the io_context to
avoid passing it through everywhere.

Tested: Capturing or passing a reference which is always valid should
not introduce any issues.

Tested on Tyan S8030:

```
Jul 01 09:59:26 s8030-bmc-30303035c0c1 entity-manager[4204]: Inventory Added: Supermicro PWS 920P SQ 0
Jul 01 09:59:26 s8030-bmc-30303035c0c1 entity-manager[4204]: Inventory Added: Supermicro PWS 920P SQ 1
Jul 01 09:59:26 s8030-bmc-30303035c0c1 entity-manager[4204]: Inventory Added: chassis
Jul 01 09:59:26 s8030-bmc-30303035c0c1 entity-manager[4204]: Inventory Added: MBX 1.57 Chassis
```

busctl tree output as before

Change-Id: Ie8f7d18c38d166c57a9cb645ab45c9103bbdff6e
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/src/entity_manager/dbus_interface.cpp b/src/entity_manager/dbus_interface.cpp
index 45c90fa..ff8094e 100644
--- a/src/entity_manager/dbus_interface.cpp
+++ b/src/entity_manager/dbus_interface.cpp
@@ -72,12 +72,12 @@
     const std::string& jsonPointerPath,
     const std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
     sdbusplus::asio::object_server& objServer,
-    nlohmann::json& systemConfiguration)
+    nlohmann::json& systemConfiguration, boost::asio::io_context& io)
 {
     std::weak_ptr<sdbusplus::asio::dbus_interface> interface = iface;
     iface->register_method(
         "Delete", [&objServer, &systemConfiguration, interface,
-                   jsonPointerPath{std::string(jsonPointerPath)}]() {
+                   jsonPointerPath{std::string(jsonPointerPath)}, &io]() {
             std::shared_ptr<sdbusplus::asio::dbus_interface> dbusInterface =
                 interface.lock();
             if (!dbusInterface)
@@ -203,7 +203,8 @@
 
 // adds simple json types to interface's properties
 void populateInterfaceFromJson(
-    nlohmann::json& systemConfiguration, const std::string& jsonPointerPath,
+    boost::asio::io_context& io, nlohmann::json& systemConfiguration,
+    const std::string& jsonPointerPath,
     std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
     nlohmann::json& dict, sdbusplus::asio::object_server& objServer,
     sdbusplus::asio::PropertyPermission permission)
@@ -238,14 +239,14 @@
     if (permission == sdbusplus::asio::PropertyPermission::readWrite)
     {
         createDeleteObjectMethod(jsonPointerPath, iface, objServer,
-                                 systemConfiguration);
+                                 systemConfiguration, io);
     }
     tryIfaceInitialize(iface);
 }
 
 void createAddObjectMethod(
-    const std::string& jsonPointerPath, const std::string& path,
-    nlohmann::json& systemConfiguration,
+    boost::asio::io_context& io, const std::string& jsonPointerPath,
+    const std::string& path, nlohmann::json& systemConfiguration,
     sdbusplus::asio::object_server& objServer, const std::string& board)
 {
     std::shared_ptr<sdbusplus::asio::dbus_interface> iface = createInterface(
@@ -255,8 +256,9 @@
         "AddObject",
         [&systemConfiguration, &objServer,
          jsonPointerPath{std::string(jsonPointerPath)}, path{std::string(path)},
-         board](const boost::container::flat_map<std::string, JsonVariantType>&
-                    data) {
+         board,
+         &io](const boost::container::flat_map<std::string, JsonVariantType>&
+                  data) {
             nlohmann::json::json_pointer ptr(jsonPointerPath);
             nlohmann::json& base = systemConfiguration[ptr];
             auto findExposes = base.find("Exposes");
@@ -363,7 +365,7 @@
             // permission is read-write, as since we just created it, must be
             // runtime modifiable
             populateInterfaceFromJson(
-                systemConfiguration,
+                io, systemConfiguration,
                 jsonPointerPath + "/Exposes/" + std::to_string(lastIndex),
                 interface, newData, objServer,
                 sdbusplus::asio::PropertyPermission::readWrite);
diff --git a/src/entity_manager/dbus_interface.hpp b/src/entity_manager/dbus_interface.hpp
index 60527e3..84cfbba 100644
--- a/src/entity_manager/dbus_interface.hpp
+++ b/src/entity_manager/dbus_interface.hpp
@@ -123,18 +123,19 @@
     const std::string& jsonPointerPath,
     const std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
     sdbusplus::asio::object_server& objServer,
-    nlohmann::json& systemConfiguration);
+    nlohmann::json& systemConfiguration, boost::asio::io_context& io);
 
 void populateInterfaceFromJson(
-    nlohmann::json& systemConfiguration, const std::string& jsonPointerPath,
+    boost::asio::io_context& io, nlohmann::json& systemConfiguration,
+    const std::string& jsonPointerPath,
     std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
     nlohmann::json& dict, sdbusplus::asio::object_server& objServer,
     sdbusplus::asio::PropertyPermission permission =
         sdbusplus::asio::PropertyPermission::readOnly);
 
 void createAddObjectMethod(
-    const std::string& jsonPointerPath, const std::string& path,
-    nlohmann::json& systemConfiguration,
+    boost::asio::io_context& io, const std::string& jsonPointerPath,
+    const std::string& path, nlohmann::json& systemConfiguration,
     sdbusplus::asio::object_server& objServer, const std::string& board);
 
 std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>&
diff --git a/src/entity_manager/entity_manager.cpp b/src/entity_manager/entity_manager.cpp
index 6a003f5..5a6955d 100644
--- a/src/entity_manager/entity_manager.cpp
+++ b/src/entity_manager/entity_manager.cpp
@@ -53,10 +53,6 @@
 static constexpr std::array<const char*, 6> settableInterfaces = {
     "FanProfile", "Pid", "Pid.Zone", "Stepwise", "Thresholds", "Polling"};
 
-// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
-boost::asio::io_context io;
-// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
-
 const std::regex illegalDbusPathRegex("[^A-Za-z0-9_.]");
 const std::regex illegalDbusMemberRegex("[^A-Za-z0-9_]");
 
@@ -69,11 +65,12 @@
 }
 
 EntityManager::EntityManager(
-    std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
+    std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+    boost::asio::io_context& io) :
     systemBus(systemBus),
     objServer(sdbusplus::asio::object_server(systemBus, /*skipManager=*/true)),
     lastJson(nlohmann::json::object()),
-    systemConfiguration(nlohmann::json::object())
+    systemConfiguration(nlohmann::json::object()), io(io)
 {
     // All other objects that EntityManager currently support are under the
     // inventory subtree.
@@ -138,11 +135,11 @@
                 boardNameOrig);
 
         dbus_interface::createAddObjectMethod(
-            jsonPointerPath, boardPath, systemConfiguration, objServer,
+            io, jsonPointerPath, boardPath, systemConfiguration, objServer,
             boardNameOrig);
 
         dbus_interface::populateInterfaceFromJson(
-            systemConfiguration, jsonPointerPath, boardIface, boardValues,
+            io, systemConfiguration, jsonPointerPath, boardIface, boardValues,
             objServer);
         jsonPointerPath += "/";
         // iterate through board properties
@@ -155,7 +152,7 @@
                                                     propName, boardNameOrig);
 
                 dbus_interface::populateInterfaceFromJson(
-                    systemConfiguration, jsonPointerPath + propName, iface,
+                    io, systemConfiguration, jsonPointerPath + propName, iface,
                     propValue, objServer);
             }
         }
@@ -219,7 +216,7 @@
                         "xyz.openbmc_project.Inventory.Item.Bmc",
                         boardNameOrig);
                 dbus_interface::populateInterfaceFromJson(
-                    systemConfiguration, jsonPointerPath, bmcIface, item,
+                    io, systemConfiguration, jsonPointerPath, bmcIface, item,
                     objServer, getPermission(itemType));
             }
             else if (itemType == "System")
@@ -230,7 +227,7 @@
                         "xyz.openbmc_project.Inventory.Item.System",
                         boardNameOrig);
                 dbus_interface::populateInterfaceFromJson(
-                    systemConfiguration, jsonPointerPath, systemIface, item,
+                    io, systemConfiguration, jsonPointerPath, systemIface, item,
                     objServer, getPermission(itemType));
             }
 
@@ -251,7 +248,7 @@
                             objServer, ifacePath, ifaceName, boardNameOrig);
 
                     dbus_interface::populateInterfaceFromJson(
-                        systemConfiguration, jsonPointerPath, objectIface,
+                        io, systemConfiguration, jsonPointerPath, objectIface,
                         config, objServer, getPermission(name));
                 }
                 else if (config.type() == nlohmann::json::value_t::array)
@@ -295,7 +292,7 @@
                                 objServer, ifacePath, ifaceName, boardNameOrig);
 
                         dbus_interface::populateInterfaceFromJson(
-                            systemConfiguration,
+                            io, systemConfiguration,
                             jsonPointerPath + "/" + std::to_string(index),
                             objectIface, arrayItem, objServer,
                             getPermission(name));
@@ -311,7 +308,7 @@
                     boardNameOrig);
 
             dbus_interface::populateInterfaceFromJson(
-                systemConfiguration, jsonPointerPath, itemIface, item,
+                io, systemConfiguration, jsonPointerPath, itemIface, item,
                 objServer, getPermission(itemType));
 
             topology.addBoard(boardPath, boardType, boardNameOrig, item);
@@ -452,7 +449,7 @@
     // NOLINTNEXTLINE(performance-unnecessary-value-param)
     const nlohmann::json newConfiguration)
 {
-    loadOverlays(newConfiguration);
+    loadOverlays(newConfiguration, io);
 
     boost::asio::post(io, [this]() {
         if (!configuration::writeJsonFiles(systemConfiguration))
@@ -514,7 +511,7 @@
         }
 
         auto perfScan = std::make_shared<scan::PerformScan>(
-            *this, *missingConfigurations, configurations,
+            *this, *missingConfigurations, configurations, io,
             [this, count, oldConfiguration, missingConfigurations]() {
                 // this is something that since ac has been applied to the bmc
                 // we saw, and we no longer see it
@@ -694,9 +691,10 @@
 
 int main()
 {
+    boost::asio::io_context io;
     auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
     systemBus->request_name("xyz.openbmc_project.EntityManager");
-    EntityManager em(systemBus);
+    EntityManager em(systemBus, io);
 
     nlohmann::json systemConfiguration = nlohmann::json::object();
 
diff --git a/src/entity_manager/entity_manager.hpp b/src/entity_manager/entity_manager.hpp
index 8490d1c..ba3914f 100644
--- a/src/entity_manager/entity_manager.hpp
+++ b/src/entity_manager/entity_manager.hpp
@@ -33,7 +33,8 @@
 {
   public:
     explicit EntityManager(
-        std::shared_ptr<sdbusplus::asio::connection>& systemBus);
+        std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+        boost::asio::io_context& io);
 
     std::shared_ptr<sdbusplus::asio::connection> systemBus;
     sdbusplus::asio::object_server objServer;
@@ -41,6 +42,7 @@
     nlohmann::json lastJson;
     nlohmann::json systemConfiguration;
     Topology topology;
+    boost::asio::io_context& io;
 
     void propertiesChangedCallback();
     void registerCallback(const std::string& path);
diff --git a/src/entity_manager/overlay.cpp b/src/entity_manager/overlay.cpp
index 7d7de96..958ced5 100644
--- a/src/entity_manager/overlay.cpp
+++ b/src/entity_manager/overlay.cpp
@@ -169,7 +169,8 @@
     const std::string& parameters, uint64_t bus, uint64_t address,
     const std::string& constructor, const std::string& destructor,
     const devices::createsHWMon hasHWMonDir,
-    std::vector<std::string> channelNames, const size_t retries = 5)
+    std::vector<std::string> channelNames, boost::asio::io_context& io,
+    const size_t retries = 5)
 {
     if (retries == 0U)
     {
@@ -193,8 +194,8 @@
             createTimer->async_wait(
                 [createTimer, name, busPath, parameters, bus, address,
                  constructor, destructor, hasHWMonDir,
-                 channelNames(std::move(channelNames)),
-                 retries](const boost::system::error_code& ec) mutable {
+                 channelNames(std::move(channelNames)), retries,
+                 &io](const boost::system::error_code& ec) mutable {
                     if (ec)
                     {
                         std::cerr << "Timer error: " << ec << "\n";
@@ -202,7 +203,8 @@
                     }
                     return buildDevice(name, busPath, parameters, bus, address,
                                        constructor, destructor, hasHWMonDir,
-                                       std::move(channelNames), retries - 1);
+                                       std::move(channelNames), io,
+                                       retries - 1);
                 });
             return -1;
         }
@@ -219,7 +221,8 @@
 
 void exportDevice(const std::string& type,
                   const devices::ExportTemplate& exportTemplate,
-                  const nlohmann::json& configuration)
+                  const nlohmann::json& configuration,
+                  boost::asio::io_context& io)
 {
     std::string parameters = exportTemplate.parameters;
     std::string busPath = exportTemplate.busPath;
@@ -273,10 +276,11 @@
     }
 
     buildDevice(name, busPath, parameters, *bus, *address, constructor,
-                destructor, hasHWMonDir, std::move(channels));
+                destructor, hasHWMonDir, std::move(channels), io);
 }
 
-bool loadOverlays(const nlohmann::json& systemConfiguration)
+bool loadOverlays(const nlohmann::json& systemConfiguration,
+                  boost::asio::io_context& io)
 {
     std::filesystem::create_directory(outputDir);
     for (auto entity = systemConfiguration.begin();
@@ -307,7 +311,7 @@
             auto device = devices::exportTemplates.find(type.c_str());
             if (device != devices::exportTemplates.end())
             {
-                exportDevice(type, device->second, configuration);
+                exportDevice(type, device->second, configuration, io);
                 continue;
             }
 
diff --git a/src/entity_manager/overlay.hpp b/src/entity_manager/overlay.hpp
index 3bc6eb7..2742de7 100644
--- a/src/entity_manager/overlay.hpp
+++ b/src/entity_manager/overlay.hpp
@@ -16,7 +16,9 @@
 /// \file overlay.hpp
 
 #pragma once
+#include <boost/asio/io_context.hpp>
 #include <nlohmann/json.hpp>
 
 void unloadAllOverlays();
-bool loadOverlays(const nlohmann::json& systemConfiguration);
+bool loadOverlays(const nlohmann::json& systemConfiguration,
+                  boost::asio::io_context& io);
diff --git a/src/entity_manager/perform_scan.cpp b/src/entity_manager/perform_scan.cpp
index 04d3c67..5e56f9c 100644
--- a/src/entity_manager/perform_scan.cpp
+++ b/src/entity_manager/perform_scan.cpp
@@ -44,7 +44,8 @@
 void getInterfaces(
     const DBusInterfaceInstance& instance,
     const std::vector<std::shared_ptr<probe::PerformProbe>>& probeVector,
-    const std::shared_ptr<scan::PerformScan>& scan, size_t retries = 5)
+    const std::shared_ptr<scan::PerformScan>& scan, boost::asio::io_context& io,
+    size_t retries = 5)
 {
     if (retries == 0U)
     {
@@ -54,8 +55,8 @@
     }
 
     scan->_em.systemBus->async_method_call(
-        [instance, scan, probeVector,
-         retries](boost::system::error_code& errc, const DBusInterface& resp) {
+        [instance, scan, probeVector, retries,
+         &io](boost::system::error_code& errc, const DBusInterface& resp) {
             if (errc)
             {
                 std::cerr << "error calling getall on  " << instance.busName
@@ -65,9 +66,9 @@
                 auto timer = std::make_shared<boost::asio::steady_timer>(io);
                 timer->expires_after(std::chrono::seconds(2));
 
-                timer->async_wait([timer, instance, scan, probeVector,
-                                   retries](const boost::system::error_code&) {
-                    getInterfaces(instance, probeVector, scan, retries - 1);
+                timer->async_wait([timer, instance, scan, probeVector, retries,
+                                   &io](const boost::system::error_code&) {
+                    getInterfaces(instance, probeVector, scan, io, retries - 1);
                 });
                 return;
             }
@@ -81,7 +82,7 @@
 static void processDbusObjects(
     std::vector<std::shared_ptr<probe::PerformProbe>>& probeVector,
     const std::shared_ptr<scan::PerformScan>& scan,
-    const GetSubTreeType& interfaceSubtree)
+    const GetSubTreeType& interfaceSubtree, boost::asio::io_context& io)
 {
     for (const auto& [path, object] : interfaceSubtree)
     {
@@ -98,7 +99,8 @@
                 // with the GetAll call to save some cycles.
                 if (!boost::algorithm::starts_with(iface, "org.freedesktop"))
                 {
-                    getInterfaces({busname, path, iface}, probeVector, scan);
+                    getInterfaces({busname, path, iface}, probeVector, scan,
+                                  io);
                 }
             }
         }
@@ -110,7 +112,8 @@
 void findDbusObjects(
     std::vector<std::shared_ptr<probe::PerformProbe>>&& probeVector,
     boost::container::flat_set<std::string>&& interfaces,
-    const std::shared_ptr<scan::PerformScan>& scan, size_t retries = 5)
+    const std::shared_ptr<scan::PerformScan>& scan, boost::asio::io_context& io,
+    size_t retries = 5)
 {
     // Filter out interfaces already obtained.
     for (const auto& [path, probeInterfaces] : scan->dbusProbeObjects)
@@ -127,9 +130,9 @@
 
     // find all connections in the mapper that expose a specific type
     scan->_em.systemBus->async_method_call(
-        [interfaces, probeVector{std::move(probeVector)}, scan,
-         retries](boost::system::error_code& ec,
-                  const GetSubTreeType& interfaceSubtree) mutable {
+        [interfaces, probeVector{std::move(probeVector)}, scan, retries,
+         &io](boost::system::error_code& ec,
+              const GetSubTreeType& interfaceSubtree) mutable {
             if (ec)
             {
                 if (ec.value() == ENOENT)
@@ -150,16 +153,16 @@
 
                 timer->async_wait(
                     [timer, interfaces{std::move(interfaces)}, scan,
-                     probeVector{std::move(probeVector)},
-                     retries](const boost::system::error_code&) mutable {
+                     probeVector{std::move(probeVector)}, retries,
+                     &io](const boost::system::error_code&) mutable {
                         findDbusObjects(std::move(probeVector),
-                                        std::move(interfaces), scan,
+                                        std::move(interfaces), scan, io,
                                         retries - 1);
                     });
                 return;
             }
 
-            processDbusObjects(probeVector, scan, interfaceSubtree);
+            processDbusObjects(probeVector, scan, interfaceSubtree, io);
         },
         "xyz.openbmc_project.ObjectMapper",
         "/xyz/openbmc_project/object_mapper",
@@ -191,12 +194,12 @@
     return std::to_string(std::hash<std::string>{}(probeName + device.dump()));
 }
 
-scan::PerformScan::PerformScan(EntityManager& em,
-                               nlohmann::json& missingConfigurations,
-                               std::list<nlohmann::json>& configurations,
-                               std::function<void()>&& callback) :
+scan::PerformScan::PerformScan(
+    EntityManager& em, nlohmann::json& missingConfigurations,
+    std::list<nlohmann::json>& configurations, boost::asio::io_context& io,
+    std::function<void()>&& callback) :
     _em(em), _missingConfigurations(missingConfigurations),
-    _configurations(configurations), _callback(std::move(callback))
+    _configurations(configurations), _callback(std::move(callback)), io(io)
 {}
 
 static void pruneRecordExposes(nlohmann::json& record)
@@ -608,7 +611,7 @@
     // probe vector stores a shared_ptr to each PerformProbe that cares
     // about a dbus interface
     findDbusObjects(std::move(dbusProbePointers),
-                    std::move(dbusProbeInterfaces), shared_from_this());
+                    std::move(dbusProbeInterfaces), shared_from_this(), io);
 }
 
 scan::PerformScan::~PerformScan()
@@ -616,7 +619,8 @@
     if (_passed)
     {
         auto nextScan = std::make_shared<PerformScan>(
-            _em, _missingConfigurations, _configurations, std::move(_callback));
+            _em, _missingConfigurations, _configurations, io,
+            std::move(_callback));
         nextScan->passedProbes = std::move(passedProbes);
         nextScan->dbusProbeObjects = std::move(dbusProbeObjects);
         nextScan->run();
diff --git a/src/entity_manager/perform_scan.hpp b/src/entity_manager/perform_scan.hpp
index 54d0e67..17396d4 100644
--- a/src/entity_manager/perform_scan.hpp
+++ b/src/entity_manager/perform_scan.hpp
@@ -27,7 +27,7 @@
 {
     PerformScan(EntityManager& em, nlohmann::json& missingConfigurations,
                 std::list<nlohmann::json>& configurations,
-                std::function<void()>&& callback);
+                boost::asio::io_context& io, std::function<void()>&& callback);
 
     void updateSystemConfiguration(const nlohmann::json& recordRef,
                                    const std::string& probeName,
@@ -41,6 +41,8 @@
     bool _passed = false;
     MapperGetSubTreeResponse dbusProbeObjects;
     std::vector<std::string> passedProbes;
+
+    boost::asio::io_context& io;
 };
 
 } // namespace scan
diff --git a/src/entity_manager/utils.hpp b/src/entity_manager/utils.hpp
index ac72c80..fb25b24 100644
--- a/src/entity_manager/utils.hpp
+++ b/src/entity_manager/utils.hpp
@@ -5,9 +5,6 @@
 #include <nlohmann/json.hpp>
 #include <sdbusplus/asio/connection.hpp>
 
-// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
-extern boost::asio::io_context io;
-
 using DBusValueVariant =
     std::variant<std::string, int64_t, uint64_t, double, int32_t, uint32_t,
                  int16_t, uint16_t, uint8_t, bool, std::vector<uint8_t>>;