]> granicus.if.org Git - icinga2/commitdiff
Fix deadlocks in the Socket/Stream classes.
authorGunnar Beutner <gunnar.beutner@netways.de>
Sat, 9 Mar 2013 14:56:56 +0000 (15:56 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 9 Mar 2013 14:56:56 +0000 (15:56 +0100)
lib/base/socket.cpp
lib/base/socket.h
lib/base/stream.cpp
lib/base/stream.h

index 196cb2bed9d1cab7a166fbbd4da1fef0b18977d7..1e88b233ed695668ff4e9a05d4f8d2f8870d4f36 100644 (file)
@@ -48,8 +48,6 @@ Socket::~Socket(void)
  */
 void Socket::Start(void)
 {
-       ObjectLock olock(this);
-
        ASSERT(!m_ReadThread.joinable() && !m_WriteThread.joinable());
        ASSERT(GetFD() != INVALID_SOCKET);
 
@@ -100,13 +98,15 @@ SOCKET Socket::GetFD(void) const
  */
 void Socket::Close(void)
 {
-       ObjectLock olock(this);
+       {
+               ObjectLock olock(this);
 
-       if (m_FD == INVALID_SOCKET)
-               return;
+               if (m_FD == INVALID_SOCKET)
+                       return;
 
-       closesocket(m_FD);
-       m_FD = INVALID_SOCKET;
+               closesocket(m_FD);
+               m_FD = INVALID_SOCKET;
+       }
 
        Stream::Close();
 }
@@ -385,19 +385,17 @@ size_t Socket::GetAvailableBytes(void) const
  */
 size_t Socket::Read(void *buffer, size_t size)
 {
-       ObjectLock olock(this);
-
-       if (m_Listening)
-               throw new logic_error("Socket does not support Read().");
-
        {
-               ObjectLock olock(m_RecvQueue);
-
-               if (m_RecvQueue->GetAvailableBytes() == 0)
-                       CheckException();
+               ObjectLock olock(this);
 
-               return m_RecvQueue->Read(buffer, size);
+               if (m_Listening)
+                       throw new logic_error("Socket does not support Read().");
        }
+
+       if (m_RecvQueue->GetAvailableBytes() == 0)
+               CheckException();
+
+       return m_RecvQueue->Read(buffer, size);
 }
 
 /**
@@ -416,14 +414,10 @@ size_t Socket::Peek(void *buffer, size_t size)
                        throw new logic_error("Socket does not support Peek().");
        }
 
-       {
-               ObjectLock olock(m_RecvQueue);
-
-               if (m_RecvQueue->GetAvailableBytes() == 0)
-                       CheckException();
+       if (m_RecvQueue->GetAvailableBytes() == 0)
+               CheckException();
 
-               return m_RecvQueue->Peek(buffer, size);
-       }
+       return m_RecvQueue->Peek(buffer, size);
 }
 
 /**
@@ -449,12 +443,13 @@ void Socket::Write(const void *buffer, size_t size)
  */
 void Socket::Listen(void)
 {
-       ObjectLock olock(this);
-
        if (listen(GetFD(), SOMAXCONN) < 0)
                BOOST_THROW_EXCEPTION(SocketException("listen() failed", GetError()));
 
-       m_Listening = true;
+       {
+               ObjectLock olock(this);
+               m_Listening = true;
+       }
 }
 
 void Socket::HandleWritable(void)
@@ -553,7 +548,7 @@ void Socket::HandleReadableServer(void)
        if (fd < 0)
                BOOST_THROW_EXCEPTION(SocketException("accept() failed", GetError()));
 
-       TcpSocket::Ptr client = boost::make_shared<TcpSocket>();
+       Socket::Ptr client = boost::make_shared<Socket>();
        client->SetFD(fd);
        OnNewClient(GetSelf(), client);
 }
index a5d86a49ca06bcc40e69fb6041189b61c32644cb..d580bd7a9fecd0611b5492a51d3478710fc9e3a2 100644 (file)
@@ -33,6 +33,7 @@ public:
        typedef shared_ptr<Socket> Ptr;
        typedef weak_ptr<Socket> WeakPtr;
 
+       Socket(void);
        ~Socket(void);
 
        virtual void Start(void);
@@ -54,8 +55,6 @@ public:
        signals2::signal<void (const Socket::Ptr&, const Socket::Ptr&)> OnNewClient;
 
 protected:
-       Socket(void);
-
        void SetFD(SOCKET fd);
        SOCKET GetFD(void) const;
 
index 235bd8bf2a13b81deed4b81a66607aec9a1bba76..cf5289b00d9702f94b1b48fb45105746e090cf1f 100644 (file)
@@ -112,3 +112,22 @@ void Stream::Close(void)
 
        SetConnected(false);
 }
+
+bool Stream::ReadLine(String *line, size_t maxLength)
+{
+       char buffer[maxLength];
+
+       size_t rc = Peek(buffer, maxLength);
+
+       for (int i = 0; i < rc; i++) {
+               if (buffer[i] == '\n') {
+                       *line = String(buffer, &(buffer[i]));
+
+                       Read(NULL, rc);
+
+                       return true;
+               }
+       }
+
+       return false;
+}
index 1e868c9016f49317caa9d5bc7f961843a21ee7a8..c02d2adbaf7006eecaadc7138ea6749a0e20b81b 100644 (file)
@@ -82,6 +82,8 @@ public:
 
        bool IsConnected(void) const;
 
+       bool ReadLine(String *line, size_t maxLength = 4096);
+
        boost::exception_ptr GetException(void);
        void CheckException(void);