summaryrefslogtreecommitdiff
path: root/lib/server/SocketStreamTLS.cpp
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2014-08-15 22:47:44 +0000
committerChris Wilson <chris+github@qwirx.com>2014-08-15 22:47:44 +0000
commit4458bf17916973aeb9e99e9166070f645fb3295e (patch)
tree26dee42145e176b7ec3c3f233c79afc7b3270557 /lib/server/SocketStreamTLS.cpp
parent06960c6241f6209b6dd19b4c204c27f1395cda7d (diff)
Fix deadlock waiting for read or write on closed connection.
If the system is suspended then it may not realise that a TCP connection has been closed, while waiting for data to arrive on it. We didn't used to apply a timeout to this read operation. Now we use the connection's default timeout on all read and write operations. Network operations that don't pass a timeout will be logged with a backtrace, so that they can be fixed.
Diffstat (limited to 'lib/server/SocketStreamTLS.cpp')
-rw-r--r--lib/server/SocketStreamTLS.cpp51
1 files changed, 8 insertions, 43 deletions
diff --git a/lib/server/SocketStreamTLS.cpp b/lib/server/SocketStreamTLS.cpp
index 127d697a..6ca172f6 100644
--- a/lib/server/SocketStreamTLS.cpp
+++ b/lib/server/SocketStreamTLS.cpp
@@ -230,16 +230,17 @@ void SocketStreamTLS::Handshake(const TLSContext &rContext, bool IsServer)
// --------------------------------------------------------------------------
bool SocketStreamTLS::WaitWhenRetryRequired(int SSLErrorCode, int Timeout)
{
- struct pollfd p;
- p.fd = GetSocketHandle();
+ CheckForMissingTimeout(Timeout);
+
+ short events;
switch(SSLErrorCode)
{
case SSL_ERROR_WANT_READ:
- p.events = POLLIN;
+ events = POLLIN;
break;
case SSL_ERROR_WANT_WRITE:
- p.events = POLLOUT;
+ events = POLLOUT;
break;
default:
@@ -247,45 +248,8 @@ bool SocketStreamTLS::WaitWhenRetryRequired(int SSLErrorCode, int Timeout)
THROW_EXCEPTION(ServerException, Internal)
break;
}
- p.revents = 0;
-
- int64_t start, end;
- start = BoxTimeToMilliSeconds(GetCurrentBoxTime());
- end = start + Timeout;
- int result;
-
- do
- {
- int64_t now = BoxTimeToMilliSeconds(GetCurrentBoxTime());
- int poll_timeout = (int)(end - now);
- if (poll_timeout < 0) poll_timeout = 0;
- if (Timeout == IOStream::TimeOutInfinite)
- {
- poll_timeout = INFTIM;
- }
- result = ::poll(&p, 1, poll_timeout);
- }
- while(result == -1 && errno == EINTR);
-
- switch(result)
- {
- case -1:
- // error - Bad!
- THROW_EXCEPTION(ServerException, SocketPollError)
- break;
-
- case 0:
- // Condition not met, timed out
- return false;
- break;
-
- default:
- // good to go!
- return true;
- break;
- }
- return true;
+ return Poll(events, Timeout);
}
// --------------------------------------------------------------------------
@@ -298,6 +262,7 @@ bool SocketStreamTLS::WaitWhenRetryRequired(int SSLErrorCode, int Timeout)
// --------------------------------------------------------------------------
int SocketStreamTLS::Read(void *pBuffer, int NBytes, int Timeout)
{
+ CheckForMissingTimeout(Timeout);
if(!mpSSL) {THROW_EXCEPTION(ServerException, TLSNoSSLObject)}
// Make sure zero byte reads work as expected
@@ -352,7 +317,7 @@ int SocketStreamTLS::Read(void *pBuffer, int NBytes, int Timeout)
// Created: 2003/08/06
//
// --------------------------------------------------------------------------
-void SocketStreamTLS::Write(const void *pBuffer, int NBytes)
+void SocketStreamTLS::Write(const void *pBuffer, int NBytes, int Timeout)
{
if(!mpSSL) {THROW_EXCEPTION(ServerException, TLSNoSSLObject)}