[icinga-checkins] icinga.org: icinga2/master: Fix deadlocks in the Socket/Stream classes.

git at icinga.org git at icinga.org
Sun Mar 10 03:09:15 CET 2013


Module: icinga2
Branch: master
Commit: 375746d710d8772405ed606563d2141a0294bf43
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=375746d710d8772405ed606563d2141a0294bf43

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Sat Mar  9 15:56:56 2013 +0100

Fix deadlocks in the Socket/Stream classes.

---

 lib/base/socket.cpp |   51 +++++++++++++++++++++++----------------------------
 lib/base/socket.h   |    3 +--
 lib/base/stream.cpp |   19 +++++++++++++++++++
 lib/base/stream.h   |    2 ++
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/lib/base/socket.cpp b/lib/base/socket.cpp
index 196cb2b..1e88b23 100644
--- a/lib/base/socket.cpp
+++ b/lib/base/socket.cpp
@@ -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);
 }
diff --git a/lib/base/socket.h b/lib/base/socket.h
index a5d86a4..d580bd7 100644
--- a/lib/base/socket.h
+++ b/lib/base/socket.h
@@ -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;
 
diff --git a/lib/base/stream.cpp b/lib/base/stream.cpp
index 235bd8b..cf5289b 100644
--- a/lib/base/stream.cpp
+++ b/lib/base/stream.cpp
@@ -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;
+}
diff --git a/lib/base/stream.h b/lib/base/stream.h
index 1e868c9..c02d2ad 100644
--- a/lib/base/stream.h
+++ b/lib/base/stream.h
@@ -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);
 





More information about the icinga-checkins mailing list