Fix loading json file causing coredump

If the json file is damaged, when the process is running and
deserializing, a coredump will occur and a cereal::RapidJSONException
will be thrown.

Error message:
```
terminate called after throwing an instance of'cereal::RapidJSONException'
what(): rapidjson internal assertion failure: IsObject()
```

Add try-catch to catch the exception, and when the exception occurs,
we need to re-serialize the json file and record the log.

Tested: Use broken json file and restart the process

hosphor-srvcfg-manager[753]: Failed to load json file, need to rewrite,
ERROR = rapidjson internal assertion failure: IsObject(),
file path = /etc/srvcfg-mgr.json

Also, we can seen a bad json file in `/tmp`, like this:
/tmp/srvcfg-mgr.json.bad

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I996e9e32f87c25d584a3b5912334d1a137b55b6c
diff --git a/src/main.cpp b/src/main.cpp
index 5723de2..2d7a4b0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -31,6 +31,7 @@
 static bool unitQueryStarted = false;
 
 static constexpr const char* srvCfgMgrFile = "/etc/srvcfg-mgr.json";
+static constexpr const char* tmpFileBad = "/tmp/srvcfg-mgr.json.bad";
 
 // Base service name list. All instance of these services and
 // units(service/socket) will be managed by this daemon.
@@ -158,26 +159,51 @@
     bool jsonExist = std::filesystem::exists(srvCfgMgrFile);
     if (jsonExist)
     {
-        std::ifstream file(srvCfgMgrFile);
-        cereal::JSONInputArchive archive(file);
-        MonitorListMap savedMonitorList;
-        archive(savedMonitorList);
-
-        // compare the unit list read from systemd1 and the save list.
-        MonitorListMap diffMap;
-        std::set_difference(begin(unitsToMonitor), end(unitsToMonitor),
-                            begin(savedMonitorList), end(savedMonitorList),
-                            std::inserter(diffMap, begin(diffMap)));
-        for (auto& unitIt : diffMap)
+        try
         {
-            auto it = savedMonitorList.find(unitIt.first);
-            if (it == savedMonitorList.end())
+            std::ifstream file(srvCfgMgrFile);
+            cereal::JSONInputArchive archive(file);
+            MonitorListMap savedMonitorList;
+            archive(savedMonitorList);
+
+            // compare the unit list read from systemd1 and the save list.
+            MonitorListMap diffMap;
+            std::set_difference(begin(unitsToMonitor), end(unitsToMonitor),
+                                begin(savedMonitorList), end(savedMonitorList),
+                                std::inserter(diffMap, begin(diffMap)));
+            for (auto& unitIt : diffMap)
             {
-                savedMonitorList.insert(unitIt);
-                updateRequired = true;
+                auto it = savedMonitorList.find(unitIt.first);
+                if (it == savedMonitorList.end())
+                {
+                    savedMonitorList.insert(unitIt);
+                    updateRequired = true;
+                }
             }
+            unitsToMonitor = savedMonitorList;
         }
-        unitsToMonitor = savedMonitorList;
+        catch (const std::exception& e)
+        {
+            lg2::error(
+                "Failed to load {FILEPATH} file, need to rewrite: {ERROR}.",
+                "FILEPATH", srvCfgMgrFile, "ERROR", e);
+
+            // The "bad" files need to be moved to /tmp/ so that we can try to
+            // find out the cause of the file corruption. If we encounter this
+            // failure multiple times, we will only overwrite it to ensure that
+            // we don't accidentally fill up /tmp/.
+            std::error_code ec;
+            std::filesystem::copy_file(
+                srvCfgMgrFile, tmpFileBad,
+                std::filesystem::copy_options::overwrite_existing, ec);
+            if (ec)
+            {
+                lg2::error("Failed to copy {SRCFILE} file to {DSTFILE}.",
+                           "SRCFILE", srvCfgMgrFile, "DSTFILE", tmpFileBad);
+            }
+
+            updateRequired = true;
+        }
     }
     if (!jsonExist || updateRequired)
     {