make ipmid respond to SIGTERM and SIGINT for clean shutdown

On some systems ipmid was not responding to SIGTERM so systemd
could not shut it down in a clean manner, resorting to SIGKILL
after a long timeout. This adds code to respond to SIGTERM and
SIGINT and safely unwind all the provider libraries on exit.

Tested-by: running ipmid; in another shell, and running
           'killall -15 ipmid' or 'killall -2 ipmid' to send
           SIGTERM or SIGINT and watch that ipmid shuts down
           in a controlled and timely manner.

Change-Id: I690846796523bebea1a08845c0d17e1df2a94fee
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/ipmid-new.cpp b/ipmid-new.cpp
index bf7795c..24d1ce5 100644
--- a/ipmid-new.cpp
+++ b/ipmid-new.cpp
@@ -63,9 +63,6 @@
 
 using namespace phosphor::logging;
 
-// Global timer for network changes
-std::unique_ptr<phosphor::Timer> networkTimer = nullptr;
-
 // IPMI Spec, shared Reservation ID.
 static unsigned short selReservationID = 0xFFFF;
 static bool selReservationValid = false;
@@ -560,7 +557,7 @@
 std::unique_ptr<phosphor::host::command::Manager> cmdManager;
 void ipmid_send_cmd_to_host(CommandHandler&& cmd)
 {
-    return cmdManager->execute(std::move(cmd));
+    return cmdManager->execute(std::forward<CommandHandler>(cmd));
 }
 
 std::unique_ptr<phosphor::host::command::Manager>& ipmid_get_host_cmd_manager()
@@ -619,9 +616,26 @@
                                                   handleLegacyIpmiCommand);
 #endif /* ALLOW_DEPRECATED_API */
 
+    // set up boost::asio signal handling
+    std::function<SignalResponse(int)> stopAsioRunLoop =
+        [&io](int signalNumber) {
+            log<level::INFO>("Received signal; quitting",
+                             entry("SIGNAL=%d", signalNumber));
+            io->stop();
+            return SignalResponse::breakExecution;
+        };
+    registerSignalHandler(ipmi::prioOpenBmcBase, SIGINT, stopAsioRunLoop);
+    registerSignalHandler(ipmi::prioOpenBmcBase, SIGTERM, stopAsioRunLoop);
+
     io->run();
 
-    // This avoids a warning about unused variables
+    // destroy all the IPMI handlers so the providers can unload safely
+    ipmi::handlerMap.clear();
+    ipmi::groupHandlerMap.clear();
+    ipmi::oemHandlerMap.clear();
+    ipmi::filterList.clear();
+    // unload the provider libraries
     handles.clear();
+
     return 0;
 }