Add Mutex Guard around open in sendPackage

The `fd` is current thread unsafe and could potentially be
access/overridden by multiple thread. Add the mutex around the open() in
sendPackage to make sure it is only called once.

Tested: Added unit tests to make sure we are thread safe.

Change-Id: I2801bace2c816ed3454c3f79b57609aa8f6ecc33
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/src/ipmiblob/ipmi_handler.cpp b/src/ipmiblob/ipmi_handler.cpp
index b51718a..3ce5d92 100644
--- a/src/ipmiblob/ipmi_handler.cpp
+++ b/src/ipmiblob/ipmi_handler.cpp
@@ -27,7 +27,9 @@
 #include <atomic>
 #include <cstdint>
 #include <cstring>
+#include <functional>
 #include <memory>
+#include <mutex>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -42,11 +44,16 @@
 
 void IpmiHandler::open()
 {
-    const int device = 0;
-    const std::vector<std::string> formats = {"/dev/ipmi", "/dev/ipmi/",
-                                              "/dev/ipmidev/"};
+    std::lock_guard<std::mutex> guard(openMutex);
+    if (fd >= 0)
+    {
+        return;
+    }
 
-    for (const auto& format : formats)
+    constexpr int device = 0;
+    const std::array<std::string, 3> formats = {"/dev/ipmi", "/dev/ipmi/",
+                                                "/dev/ipmidev/"};
+    for (const std::string& format : formats)
     {
         std::ostringstream path;
         path << format << device;
@@ -69,10 +76,7 @@
     IpmiHandler::sendPacket(std::uint8_t netfn, std::uint8_t cmd,
                             std::vector<std::uint8_t>& data)
 {
-    if (fd < 0)
-    {
-        open();
-    }
+    open();
 
     constexpr int ipmiOEMLun = 0;
     constexpr int fifteenMs = 15 * 1000;
@@ -126,7 +130,7 @@
             {
                 continue;
             }
-            throw IpmiException("Error occurred.");
+            throw IpmiException("Polling Error occurred.");
         }
         else if (rc == 0)
         {
diff --git a/src/ipmiblob/ipmi_handler.hpp b/src/ipmiblob/ipmi_handler.hpp
index fedc068..2564e37 100644
--- a/src/ipmiblob/ipmi_handler.hpp
+++ b/src/ipmiblob/ipmi_handler.hpp
@@ -5,6 +5,7 @@
 
 #include <atomic>
 #include <memory>
+#include <mutex>
 #include <vector>
 
 namespace ipmiblob
@@ -49,6 +50,9 @@
     int fd = -1;
     /* The last IPMI sequence number we used. */
     std::atomic_int sequence = 0;
+
+    // Protect the open fd between different threads
+    std::mutex openMutex;
 };
 
 } // namespace ipmiblob