Fix deadlocks in the Socket/Stream classes.

This commit is contained in:
Gunnar Beutner 2013-03-09 15:56:56 +01:00
parent 5a861b0de0
commit 375746d710
4 changed files with 45 additions and 30 deletions

View 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);
ObjectLock olock(this);
if (m_RecvQueue->GetAvailableBytes() == 0)
CheckException();
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);
}

View 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;

View 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;
}

View 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);