]> granicus.if.org Git - icinga2/commitdiff
Another attempt at fixing the API deadlock
authorGunnar Beutner <gunnar@beutner.name>
Tue, 1 Jul 2014 07:38:22 +0000 (09:38 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 1 Jul 2014 07:41:02 +0000 (09:41 +0200)
fixes #6617

lib/remote/apiclient.cpp
lib/remote/apiclient.hpp
lib/remote/apilistener.cpp

index 9203094f102b7517927e2dc318934056fad0fa70..e7a2c5cb059c8813a661439d1aca3d40dcf1f582 100644 (file)
@@ -65,6 +65,17 @@ ConnectionRole ApiClient::GetRole(void) const
 }
 
 void ApiClient::SendMessage(const Dictionary::Ptr& message)
+{
+       if (m_WriteQueue.GetLength() > 5000) {
+               Log(LogWarning, "remote", "Closing connection for API identity '" + m_Identity + "': Too many queued messages.");
+               Disconnect();
+               return;
+       }
+
+       m_WriteQueue.Enqueue(boost::bind(&ApiClient::SendMessageSync, this, message));
+}
+
+void ApiClient::SendMessageSync(const Dictionary::Ptr& message)
 {
        try {
                ObjectLock olock(m_Stream);
index b491708c0fcc9f8f71157327b63d503812f2b1b9..b6d87e068856f4f1d745e6fe679303f43b34143f 100644 (file)
@@ -23,6 +23,7 @@
 #include "remote/endpoint.hpp"
 #include "base/stream.hpp"
 #include "base/timer.hpp"
+#include "base/workqueue.hpp"
 #include "remote/i2-remote.hpp"
 
 namespace icinga
@@ -64,8 +65,11 @@ private:
        ConnectionRole m_Role;
        double m_Seen;
 
+       WorkQueue m_WriteQueue;
+
        bool ProcessMessage(void);
        void MessageThreadProc(void);
+       void SendMessageSync(const Dictionary::Ptr& request);
 };
 
 }
index c666a701b459330bf8a3ead9dc8bcaf64c05f210..5f981bd600f340f5cd7eddac8e34a66fb5f7a4cb 100644 (file)
@@ -364,6 +364,10 @@ void ApiListener::ApiTimerHandler(void)
                                if (endpoint->GetHost().IsEmpty() || endpoint->GetPort().IsEmpty())
                                        continue;
 
+                               /* don't try to connect if there's already a connection attempt */
+                               if (endpoint->GetConnecting())
+                                       continue;
+
                                Utility::QueueAsyncCallback(boost::bind(&ApiListener::AddConnection, this, endpoint));
                        }
                }