Check if the object is still valid in the timeout callback function

When the SOL module in netipmid is busy, there is a chance that the
timeout callback function is executed after the context object is
destructed.  This will cause the process to crash with this error:

terminate called after throwing an instance of
'boost::wrapexcept<boost::asio::bad_executor>'
  what():  bad executor

The root cause is that the cancel() cannot cancel the expired callback
handlers. When the callback handler is executed, the object is deleted
already.

This uses proper reference counting on the objects captured in the
lambda so that they are not referencing memory that has already gone out
of scope.

Tested:
Decrease the accumulateInterval to 50ms for easy reproducing.
Run "ipmitool sel list", "ipmitool sensor list"
and "ipmitool sol looptest 200 500" at the same time,
no "sol looptest fail" error

Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Change-Id: I4b9e4ebce14ff5fca8e991aed96643186c9ea5d9
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
index 215f725..3b2b892 100644
--- a/sol/sol_context.cpp
+++ b/sol/sol_context.cpp
@@ -19,7 +19,17 @@
     sessionID(sessionID)
 {
     session = std::get<session::Manager&>(singletonPool).getSession(sessionID);
-    enableAccumulateTimer(true);
+}
+
+std::shared_ptr<Context>
+    Context::makeContext(std::shared_ptr<boost::asio::io_context> io,
+                         uint8_t maxRetryCount, uint8_t sendThreshold,
+                         uint8_t instance, session::SessionID sessionID)
+{
+    auto ctx = std::make_shared<Context>(io, maxRetryCount, sendThreshold,
+                                         instance, sessionID);
+    ctx->enableAccumulateTimer(true);
+    return ctx;
 }
 
 void Context::enableAccumulateTimer(bool enable)
@@ -30,12 +40,15 @@
     if (enable)
     {
         accumulateTimer.expires_after(interval);
-        accumulateTimer.async_wait([this](const boost::system::error_code& ec) {
-            if (!ec)
-            {
-                charAccTimerHandler();
-            }
-        });
+        std::weak_ptr<Context> weakRef = weak_from_this();
+        accumulateTimer.async_wait(
+            [weakRef](const boost::system::error_code& ec) {
+                std::shared_ptr<Context> self = weakRef.lock();
+                if (!ec && self)
+                {
+                    self->charAccTimerHandler();
+                }
+            });
     }
     else
     {
@@ -51,10 +64,12 @@
         std::chrono::microseconds interval =
             std::get<sol::Manager&>(singletonPool).retryInterval;
         retryTimer.expires_after(interval);
-        retryTimer.async_wait([this](const boost::system::error_code& ec) {
-            if (!ec)
+        std::weak_ptr<Context> weakRef = weak_from_this();
+        retryTimer.async_wait([weakRef](const boost::system::error_code& ec) {
+            std::shared_ptr<Context> self = weakRef.lock();
+            if (!ec && self)
             {
-                retryTimerHandler();
+                self->retryTimerHandler();
             }
         });
     }