Ver Fonte

fix a deadlock or sporadic crash during shutdown

Sven Czarnian há 3 anos atrás
pai
commit
d06ec49b2e

+ 2 - 3
include/aman/com/AircraftReporter.h

@@ -21,15 +21,14 @@ namespace aman {
      */
     class AircraftReporter {
     private:
-        bool          m_initialized;
-        zmq::socket_t m_socket;
+        std::unique_ptr<zmq::socket_t> m_socket;
 
         AircraftReporter() noexcept;
 
         template <typename T>
         bool setSocketKey(const std::string& key, T entry) {
             try {
-                this->m_socket.set(entry, key);
+                this->m_socket->set(entry, key);
                 return true;
             }
             catch (std::exception&) {

+ 5 - 0
src/PlugIn.cpp

@@ -20,7 +20,9 @@
 #include <aman/config/IdentifierFileFormat.h>
 
 #include <protobuf/AircraftReport.pb.h>
+#include <zmq.h>
 
+#include "com/ZmqContext.h"
 #include "PlugIn.h"
 
 EXTERN_C IMAGE_DOS_HEADER __ImageBase;
@@ -59,6 +61,8 @@ PlugIn::PlugIn() :
         return;
     }
 
+    ZmqContext::instance().initialize();
+
     if (false == AircraftReporter::instance().initialize(this->m_configuration)) {
         this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to initialize the reporter-connection to the backend", true, true, true, true, true);
         return;
@@ -67,6 +71,7 @@ PlugIn::PlugIn() :
 
 PlugIn::~PlugIn() noexcept {
     AircraftReporter::instance().deinitialize();
+    ZmqContext::instance().deinitialize();
     google::protobuf::ShutdownProtobufLibrary();
 }
 

+ 16 - 13
src/com/AircraftReporter.cpp

@@ -16,15 +16,16 @@
 using namespace aman;
 
 AircraftReporter::AircraftReporter() noexcept :
-        m_initialized(false),
         m_socket() { }
 
 bool AircraftReporter::initialize(const Communication& configuration) {
-    if (true == this->m_initialized || false == configuration.valid)
-        return this->m_initialized;
+    if (nullptr != this->m_socket)
+        return true;
+    if (false == configuration.valid)
+        return false;
 
-    this->m_socket = zmq::socket_t(ZmqContext::context(), zmq::socket_type::pub);
-    this->m_socket.set(zmq::sockopt::immediate, true);
+    this->m_socket = std::make_unique<zmq::socket_t>(ZmqContext::instance().context(), zmq::socket_type::pub);
+    this->m_socket->set(zmq::sockopt::immediate, true);
 
     /* configure the encryption */
     if (false == this->setSocketKey(configuration.serverPublicIdentifier, zmq::sockopt::curve_serverkey))
@@ -36,32 +37,34 @@ bool AircraftReporter::initialize(const Communication& configuration) {
 
     /* connect to the server */
     try {
-        this->m_socket.connect("tcp://" + configuration.address + ":" + std::to_string(configuration.portReporter));
+        this->m_socket->connect("tcp://" + configuration.address + ":" + std::to_string(configuration.portReporter));
     }
     catch (zmq::error_t&) {
+        this->m_socket = std::unique_ptr<zmq::socket_t>();
         return false;
     }
 
-    this->m_initialized = true;
     return true;
 }
 
 bool AircraftReporter::deinitialize() {
-    if (false == this->m_initialized)
+    if (nullptr == this->m_socket)
         return true;
 
-    this->m_socket.close();
+    this->m_socket->close();
+    this->m_socket = std::make_unique<zmq::socket_t>();
+
     return true;
 }
 
 bool AircraftReporter::send(zmq::message_t& message) {
     bool retval = false;
 
-    if (true == this->m_initialized) {
+    if (nullptr != this->m_socket) {
         try {
-            auto bla = message.size();
-            auto result = this->m_socket.send(message, zmq::send_flags::none);
-            retval = result.value() == bla;
+            auto size = message.size();
+            auto result = this->m_socket->send(message, zmq::send_flags::none);
+            retval = result.value() == size;
         }
         catch (zmq::error_t&) {
             return false;

+ 17 - 2
src/com/ZmqContext.cpp

@@ -13,8 +13,23 @@
 
 using namespace aman;
 
-static zmq::context_t __context(2);
+ZmqContext::ZmqContext() : m_context() { }
+
+void ZmqContext::initialize() {
+    if (nullptr == this->m_context)
+        this->m_context = std::make_unique<zmq::context_t>(2);
+}
+
+void ZmqContext::deinitialize() {
+    if (nullptr != this->m_context)
+        this->m_context = std::unique_ptr<zmq::context_t>();
+}
 
 zmq::context_t& ZmqContext::context() {
-    return __context;
+    return *this->m_context;
+}
+
+ZmqContext& ZmqContext::instance() {
+    static ZmqContext __instance;
+    return __instance;
 }

+ 17 - 1
src/com/ZmqContext.h

@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include <memory>
+
 #include <zmq.hpp>
 
 namespace aman {
@@ -15,11 +17,25 @@ namespace aman {
      * @brief Handles the ZMQ context information
      */
     class ZmqContext {
+    private:
+        ZmqContext();
+
+        std::unique_ptr<zmq::context_t> m_context;
+
     public:
+        ZmqContext(const ZmqContext&) = delete;
+        ZmqContext(ZmqContext&&) = delete;
+        ZmqContext& operator=(const ZmqContext&) = delete;
+        ZmqContext& operator=(ZmqContext&&) = delete;
+
+        void initialize();
+        void deinitialize();
+
         /**
          * @brief Returns the system wide context
          * @return The ZMQ context
          */
-        static zmq::context_t& context();
+        zmq::context_t& context();
+        static ZmqContext& instance();
     };
 }