summaryrefslogtreecommitdiff
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
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.
-rw-r--r--bin/bbackupd/BackupClientDirectoryRecord.cpp3
-rw-r--r--lib/backupstore/BackupStoreFile.cpp3
-rw-r--r--lib/backupstore/BackupStoreFile.h3
-rw-r--r--lib/backupstore/BackupStoreFileCmbIdx.cpp6
-rw-r--r--lib/backupstore/BackupStoreFileEncodeStream.cpp3
-rw-r--r--lib/backupstore/BackupStoreFileEncodeStream.h3
-rw-r--r--lib/common/BufferedStream.cpp2
-rw-r--r--lib/common/BufferedStream.h3
-rw-r--r--lib/common/BufferedWriteStream.cpp2
-rw-r--r--lib/common/BufferedWriteStream.h3
-rw-r--r--lib/common/CollectInBufferStream.cpp2
-rw-r--r--lib/common/CollectInBufferStream.h3
-rw-r--r--lib/common/FileStream.cpp2
-rw-r--r--lib/common/FileStream.h3
-rw-r--r--lib/common/IOStream.h3
-rw-r--r--lib/common/MemBlockStream.cpp2
-rw-r--r--lib/common/MemBlockStream.h3
-rw-r--r--lib/common/PartialReadStream.cpp2
-rw-r--r--lib/common/PartialReadStream.h3
-rw-r--r--lib/common/RateLimitingStream.h5
-rw-r--r--lib/common/ReadGatherStream.cpp2
-rw-r--r--lib/common/ReadGatherStream.h3
-rw-r--r--lib/common/ReadLoggingStream.cpp2
-rw-r--r--lib/common/ReadLoggingStream.h3
-rw-r--r--lib/common/SelfFlushingStream.h5
-rw-r--r--lib/common/StreamableMemBlock.cpp8
-rw-r--r--lib/common/ZeroStream.cpp2
-rw-r--r--lib/common/ZeroStream.h3
-rw-r--r--lib/raidfile/RaidFileRead.cpp2
-rw-r--r--lib/raidfile/RaidFileRead.h3
-rw-r--r--lib/raidfile/RaidFileWrite.cpp2
-rw-r--r--lib/raidfile/RaidFileWrite.h3
-rw-r--r--lib/server/ProtocolUncertainStream.cpp2
-rw-r--r--lib/server/ProtocolUncertainStream.h3
-rw-r--r--lib/server/SocketStream.cpp82
-rw-r--r--lib/server/SocketStream.h24
-rw-r--r--lib/server/SocketStreamTLS.cpp51
-rw-r--r--lib/server/SocketStreamTLS.h3
38 files changed, 159 insertions, 103 deletions
diff --git a/bin/bbackupd/BackupClientDirectoryRecord.cpp b/bin/bbackupd/BackupClientDirectoryRecord.cpp
index 897c02e4..9fa745ec 100644
--- a/bin/bbackupd/BackupClientDirectoryRecord.cpp
+++ b/bin/bbackupd/BackupClientDirectoryRecord.cpp
@@ -663,7 +663,8 @@ BackupClientDirectoryRecord::FetchDirectoryListing(BackupClientDirectoryRecord::
true /* want attributes */));
// Retrieve the directory from the stream following
- apDir.reset(new BackupStoreDirectory(connection.ReceiveStream()));
+ apDir.reset(new BackupStoreDirectory(connection.ReceiveStream(),
+ connection.GetTimeout()));
return apDir;
}
diff --git a/lib/backupstore/BackupStoreFile.cpp b/lib/backupstore/BackupStoreFile.cpp
index d4c73f8b..07ea1637 100644
--- a/lib/backupstore/BackupStoreFile.cpp
+++ b/lib/backupstore/BackupStoreFile.cpp
@@ -838,7 +838,8 @@ bool BackupStoreFile::DecodedStream::IsSymLink()
// Created: 9/12/03
//
// --------------------------------------------------------------------------
-void BackupStoreFile::DecodedStream::Write(const void *pBuffer, int NBytes)
+void BackupStoreFile::DecodedStream::Write(const void *pBuffer, int NBytes,
+ int Timeout)
{
THROW_EXCEPTION(BackupStoreException, CantWriteToDecodedFileStream)
}
diff --git a/lib/backupstore/BackupStoreFile.h b/lib/backupstore/BackupStoreFile.h
index 776e6d22..854470df 100644
--- a/lib/backupstore/BackupStoreFile.h
+++ b/lib/backupstore/BackupStoreFile.h
@@ -87,7 +87,8 @@ public:
// Stream functions
virtual int Read(void *pBuffer, int NBytes, int Timeout);
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
diff --git a/lib/backupstore/BackupStoreFileCmbIdx.cpp b/lib/backupstore/BackupStoreFileCmbIdx.cpp
index c8bcc3b9..0eec3872 100644
--- a/lib/backupstore/BackupStoreFileCmbIdx.cpp
+++ b/lib/backupstore/BackupStoreFileCmbIdx.cpp
@@ -32,7 +32,8 @@ public:
~BSFCombinedIndexStream();
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
virtual void Initialise(IOStream &rFrom);
@@ -289,7 +290,8 @@ int BSFCombinedIndexStream::Read(void *pBuffer, int NBytes, int Timeout)
// Created: 8/7/04
//
// --------------------------------------------------------------------------
-void BSFCombinedIndexStream::Write(const void *pBuffer, int NBytes)
+void BSFCombinedIndexStream::Write(const void *pBuffer, int NBytes,
+ int Timeout)
{
THROW_EXCEPTION(BackupStoreException, StreamDoesntHaveRequiredFeatures)
}
diff --git a/lib/backupstore/BackupStoreFileEncodeStream.cpp b/lib/backupstore/BackupStoreFileEncodeStream.cpp
index b40bcd08..ccab8074 100644
--- a/lib/backupstore/BackupStoreFileEncodeStream.cpp
+++ b/lib/backupstore/BackupStoreFileEncodeStream.cpp
@@ -667,7 +667,8 @@ void BackupStoreFileEncodeStream::StoreBlockIndexEntry(int64_t EncSizeOrBlkIndex
// Created: 8/12/03
//
// --------------------------------------------------------------------------
-void BackupStoreFileEncodeStream::Write(const void *pBuffer, int NBytes)
+void BackupStoreFileEncodeStream::Write(const void *pBuffer, int NBytes,
+ int Timeout)
{
THROW_EXCEPTION(BackupStoreException, CantWriteToEncodedFileStream)
}
diff --git a/lib/backupstore/BackupStoreFileEncodeStream.h b/lib/backupstore/BackupStoreFileEncodeStream.h
index 80bdff58..13648d47 100644
--- a/lib/backupstore/BackupStoreFileEncodeStream.h
+++ b/lib/backupstore/BackupStoreFileEncodeStream.h
@@ -83,7 +83,8 @@ public:
BackgroundTask* pBackgroundTask = NULL);
virtual int Read(void *pBuffer, int NBytes, int Timeout);
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
int64_t GetTotalBytesSent() { return mTotalBytesSent; }
diff --git a/lib/common/BufferedStream.cpp b/lib/common/BufferedStream.cpp
index b58253f3..cef0a73f 100644
--- a/lib/common/BufferedStream.cpp
+++ b/lib/common/BufferedStream.cpp
@@ -96,7 +96,7 @@ IOStream::pos_type BufferedStream::BytesLeftToRead()
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void BufferedStream::Write(const void *pBuffer, int NBytes)
+void BufferedStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, NotSupported);
}
diff --git a/lib/common/BufferedStream.h b/lib/common/BufferedStream.h
index 4987e37b..3984aceb 100644
--- a/lib/common/BufferedStream.h
+++ b/lib/common/BufferedStream.h
@@ -25,7 +25,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(IOStream::pos_type Offset, int SeekType);
virtual void Close();
diff --git a/lib/common/BufferedWriteStream.cpp b/lib/common/BufferedWriteStream.cpp
index 797be00d..8fbabe9b 100644
--- a/lib/common/BufferedWriteStream.cpp
+++ b/lib/common/BufferedWriteStream.cpp
@@ -64,7 +64,7 @@ IOStream::pos_type BufferedWriteStream::BytesLeftToRead()
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void BufferedWriteStream::Write(const void *pBuffer, int NBytes)
+void BufferedWriteStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
int numBytesRemain = NBytes;
diff --git a/lib/common/BufferedWriteStream.h b/lib/common/BufferedWriteStream.h
index 7a1c8c17..5f6d5f19 100644
--- a/lib/common/BufferedWriteStream.h
+++ b/lib/common/BufferedWriteStream.h
@@ -25,7 +25,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(IOStream::pos_type Offset, int SeekType);
virtual void Flush(int Timeout = IOStream::TimeOutInfinite);
diff --git a/lib/common/CollectInBufferStream.cpp b/lib/common/CollectInBufferStream.cpp
index 90e2e7bc..47b271f0 100644
--- a/lib/common/CollectInBufferStream.cpp
+++ b/lib/common/CollectInBufferStream.cpp
@@ -98,7 +98,7 @@ IOStream::pos_type CollectInBufferStream::BytesLeftToRead()
// Created: 2003/08/26
//
// --------------------------------------------------------------------------
-void CollectInBufferStream::Write(const void *pBuffer, int NBytes)
+void CollectInBufferStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
if(mInWritePhase != true) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
diff --git a/lib/common/CollectInBufferStream.h b/lib/common/CollectInBufferStream.h
index d73af8db..03cb5da8 100644
--- a/lib/common/CollectInBufferStream.h
+++ b/lib/common/CollectInBufferStream.h
@@ -34,7 +34,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(pos_type Offset, int SeekType);
virtual bool StreamDataLeft();
diff --git a/lib/common/FileStream.cpp b/lib/common/FileStream.cpp
index 62fa05f4..6d5810dc 100644
--- a/lib/common/FileStream.cpp
+++ b/lib/common/FileStream.cpp
@@ -246,7 +246,7 @@ IOStream::pos_type FileStream::BytesLeftToRead()
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void FileStream::Write(const void *pBuffer, int NBytes)
+void FileStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
if(mOSFileHandle == INVALID_FILE)
{
diff --git a/lib/common/FileStream.h b/lib/common/FileStream.h
index 8489188c..f528b8bc 100644
--- a/lib/common/FileStream.h
+++ b/lib/common/FileStream.h
@@ -40,7 +40,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(IOStream::pos_type Offset, int SeekType);
virtual void Close();
diff --git a/lib/common/IOStream.h b/lib/common/IOStream.h
index 81f1cfa6..a4eb3db1 100644
--- a/lib/common/IOStream.h
+++ b/lib/common/IOStream.h
@@ -47,7 +47,8 @@ public:
typedef int64_t pos_type;
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite) = 0;
virtual pos_type BytesLeftToRead(); // may return IOStream::SizeOfStreamUnknown (and will for most stream types)
- virtual void Write(const void *pBuffer, int NBytes) = 0;
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite) = 0;
virtual void Write(const char *pBuffer);
virtual void WriteAllBuffered();
virtual pos_type GetPosition() const;
diff --git a/lib/common/MemBlockStream.cpp b/lib/common/MemBlockStream.cpp
index 90c0eaf6..f49ac96f 100644
--- a/lib/common/MemBlockStream.cpp
+++ b/lib/common/MemBlockStream.cpp
@@ -179,7 +179,7 @@ IOStream::pos_type MemBlockStream::BytesLeftToRead()
// Created: 2003/09/05
//
// --------------------------------------------------------------------------
-void MemBlockStream::Write(const void *pBuffer, int NBytes)
+void MemBlockStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, MemBlockStreamNotSupported)
}
diff --git a/lib/common/MemBlockStream.h b/lib/common/MemBlockStream.h
index 98398121..1ba4b0a6 100644
--- a/lib/common/MemBlockStream.h
+++ b/lib/common/MemBlockStream.h
@@ -38,7 +38,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(pos_type Offset, int SeekType);
virtual bool StreamDataLeft();
diff --git a/lib/common/PartialReadStream.cpp b/lib/common/PartialReadStream.cpp
index f2f79715..b5f99bb5 100644
--- a/lib/common/PartialReadStream.cpp
+++ b/lib/common/PartialReadStream.cpp
@@ -104,7 +104,7 @@ IOStream::pos_type PartialReadStream::BytesLeftToRead()
// Created: 2003/08/26
//
// --------------------------------------------------------------------------
-void PartialReadStream::Write(const void *pBuffer, int NBytes)
+void PartialReadStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, CantWriteToPartialReadStream)
}
diff --git a/lib/common/PartialReadStream.h b/lib/common/PartialReadStream.h
index 1b46b0bd..61bdd7d1 100644
--- a/lib/common/PartialReadStream.h
+++ b/lib/common/PartialReadStream.h
@@ -33,7 +33,8 @@ private:
public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
diff --git a/lib/common/RateLimitingStream.h b/lib/common/RateLimitingStream.h
index a322b99b..cd9d8271 100644
--- a/lib/common/RateLimitingStream.h
+++ b/lib/common/RateLimitingStream.h
@@ -30,9 +30,10 @@ public:
int Timeout = IOStream::TimeOutInfinite);
// Everything else is delegated to the sink
- virtual void Write(const void *pBuffer, int NBytes)
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite)
{
- Write(pBuffer, NBytes);
+ Write(pBuffer, NBytes, Timeout);
}
virtual pos_type BytesLeftToRead()
{
diff --git a/lib/common/ReadGatherStream.cpp b/lib/common/ReadGatherStream.cpp
index f50e6664..ae252832 100644
--- a/lib/common/ReadGatherStream.cpp
+++ b/lib/common/ReadGatherStream.cpp
@@ -213,7 +213,7 @@ IOStream::pos_type ReadGatherStream::BytesLeftToRead()
// Created: 10/12/03
//
// --------------------------------------------------------------------------
-void ReadGatherStream::Write(const void *pBuffer, int NBytes)
+void ReadGatherStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, CannotWriteToReadGatherStream);
}
diff --git a/lib/common/ReadGatherStream.h b/lib/common/ReadGatherStream.h
index 613ede3e..9a44480b 100644
--- a/lib/common/ReadGatherStream.h
+++ b/lib/common/ReadGatherStream.h
@@ -37,7 +37,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
virtual pos_type GetPosition() const;
diff --git a/lib/common/ReadLoggingStream.cpp b/lib/common/ReadLoggingStream.cpp
index 54c99c95..df493344 100644
--- a/lib/common/ReadLoggingStream.cpp
+++ b/lib/common/ReadLoggingStream.cpp
@@ -96,7 +96,7 @@ IOStream::pos_type ReadLoggingStream::BytesLeftToRead()
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void ReadLoggingStream::Write(const void *pBuffer, int NBytes)
+void ReadLoggingStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, NotSupported);
}
diff --git a/lib/common/ReadLoggingStream.h b/lib/common/ReadLoggingStream.h
index b23b542c..4a01a45c 100644
--- a/lib/common/ReadLoggingStream.h
+++ b/lib/common/ReadLoggingStream.h
@@ -39,7 +39,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(IOStream::pos_type Offset, int SeekType);
virtual void Close();
diff --git a/lib/common/SelfFlushingStream.h b/lib/common/SelfFlushingStream.h
index 6865ab96..b4efa294 100644
--- a/lib/common/SelfFlushingStream.h
+++ b/lib/common/SelfFlushingStream.h
@@ -56,9 +56,10 @@ public:
{
return mrSource.BytesLeftToRead();
}
- virtual void Write(const void *pBuffer, int NBytes)
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite)
{
- mrSource.Write(pBuffer, NBytes);
+ mrSource.Write(pBuffer, NBytes, Timeout);
}
virtual bool StreamDataLeft()
{
diff --git a/lib/common/StreamableMemBlock.cpp b/lib/common/StreamableMemBlock.cpp
index b376f037..be3d0031 100644
--- a/lib/common/StreamableMemBlock.cpp
+++ b/lib/common/StreamableMemBlock.cpp
@@ -252,7 +252,9 @@ void StreamableMemBlock::ReadFromStream(IOStream &rStream, int Timeout)
{
// Get the size of the block
int32_t size_s;
- if(!rStream.ReadFullBuffer(&size_s, sizeof(size_s), 0 /* not interested in bytes read if this fails */))
+ if(!rStream.ReadFullBuffer(&size_s, sizeof(size_s),
+ 0, /* not interested in bytes read if this fails */
+ Timeout))
{
THROW_EXCEPTION(CommonException, StreamableMemBlockIncompleteRead)
}
@@ -270,7 +272,9 @@ void StreamableMemBlock::ReadFromStream(IOStream &rStream, int Timeout)
try
{
// Read in
- if(!rStream.ReadFullBuffer(pblock, size, 0 /* not interested in bytes read if this fails */))
+ if(!rStream.ReadFullBuffer(pblock, size,
+ 0, /* not interested in bytes read if this fails */
+ Timeout))
{
THROW_EXCEPTION(CommonException, StreamableMemBlockIncompleteRead)
}
diff --git a/lib/common/ZeroStream.cpp b/lib/common/ZeroStream.cpp
index d11ed80c..e1342e6f 100644
--- a/lib/common/ZeroStream.cpp
+++ b/lib/common/ZeroStream.cpp
@@ -76,7 +76,7 @@ IOStream::pos_type ZeroStream::BytesLeftToRead()
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void ZeroStream::Write(const void *pBuffer, int NBytes)
+void ZeroStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(CommonException, NotSupported);
}
diff --git a/lib/common/ZeroStream.h b/lib/common/ZeroStream.h
index 0119045b..f91221b0 100644
--- a/lib/common/ZeroStream.h
+++ b/lib/common/ZeroStream.h
@@ -22,7 +22,8 @@ public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(IOStream::pos_type Offset, int SeekType);
virtual void Close();
diff --git a/lib/raidfile/RaidFileRead.cpp b/lib/raidfile/RaidFileRead.cpp
index 7591961f..a78ec4a2 100644
--- a/lib/raidfile/RaidFileRead.cpp
+++ b/lib/raidfile/RaidFileRead.cpp
@@ -1721,7 +1721,7 @@ bool RaidFileRead::ReadDirectoryContents(int SetNumber, const std::string &rDirN
// Created: 2003/08/21
//
// --------------------------------------------------------------------------
-void RaidFileRead::Write(const void *pBuffer, int NBytes)
+void RaidFileRead::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(RaidFileException, UnsupportedReadWriteOrClose)
}
diff --git a/lib/raidfile/RaidFileRead.h b/lib/raidfile/RaidFileRead.h
index e746ed46..570443c8 100644
--- a/lib/raidfile/RaidFileRead.h
+++ b/lib/raidfile/RaidFileRead.h
@@ -56,7 +56,8 @@ public:
static bool ReadDirectoryContents(int SetNumber, const std::string &rDirName, int DirReadType, std::vector<std::string> &rOutput);
// Common IOStream interface implementation
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamClosed();
virtual pos_type BytesLeftToRead();
diff --git a/lib/raidfile/RaidFileWrite.cpp b/lib/raidfile/RaidFileWrite.cpp
index 82aeef3d..ddc99fc7 100644
--- a/lib/raidfile/RaidFileWrite.cpp
+++ b/lib/raidfile/RaidFileWrite.cpp
@@ -243,7 +243,7 @@ void RaidFileWrite::Open(bool AllowOverwrite)
// Created: 2003/07/10
//
// --------------------------------------------------------------------------
-void RaidFileWrite::Write(const void *pBuffer, int Length)
+void RaidFileWrite::Write(const void *pBuffer, int Length, int Timeout)
{
// open?
if(mOSFileHandle == -1)
diff --git a/lib/raidfile/RaidFileWrite.h b/lib/raidfile/RaidFileWrite.h
index e2887167..4c5e8178 100644
--- a/lib/raidfile/RaidFileWrite.h
+++ b/lib/raidfile/RaidFileWrite.h
@@ -47,7 +47,8 @@ private:
public:
// IOStream interface
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); // will exception
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual pos_type GetPosition() const;
virtual void Seek(pos_type Offset, int SeekType);
virtual void Close(); // will discard the file! Use commit instead.
diff --git a/lib/server/ProtocolUncertainStream.cpp b/lib/server/ProtocolUncertainStream.cpp
index 336fd36d..aeb15816 100644
--- a/lib/server/ProtocolUncertainStream.cpp
+++ b/lib/server/ProtocolUncertainStream.cpp
@@ -173,7 +173,7 @@ IOStream::pos_type ProtocolUncertainStream::BytesLeftToRead()
// Created: 2003/12/05
//
// --------------------------------------------------------------------------
-void ProtocolUncertainStream::Write(const void *pBuffer, int NBytes)
+void ProtocolUncertainStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
THROW_EXCEPTION(ServerException, CantWriteToProtocolUncertainStream)
}
diff --git a/lib/server/ProtocolUncertainStream.h b/lib/server/ProtocolUncertainStream.h
index 4954cf88..2e97ba6a 100644
--- a/lib/server/ProtocolUncertainStream.h
+++ b/lib/server/ProtocolUncertainStream.h
@@ -33,7 +33,8 @@ private:
public:
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
virtual pos_type BytesLeftToRead();
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual bool StreamDataLeft();
virtual bool StreamClosed();
diff --git a/lib/server/SocketStream.cpp b/lib/server/SocketStream.cpp
index 7b46b024..dafb4338 100644
--- a/lib/server/SocketStream.cpp
+++ b/lib/server/SocketStream.cpp
@@ -34,6 +34,7 @@
#include "SocketStream.h"
#include "CommonException.h"
#include "Socket.h"
+#include "Utils.h"
#include "MemLeakFindOn.h"
@@ -204,7 +205,9 @@ void SocketStream::Open(Socket::Type Type, const std::string& rName, int Port)
// --------------------------------------------------------------------------
int SocketStream::Read(void *pBuffer, int NBytes, int Timeout)
{
- if(mSocketHandle == INVALID_SOCKET_VALUE)
+ CheckForMissingTimeout(Timeout);
+
+ if(mSocketHandle == INVALID_SOCKET_VALUE)
{
THROW_EXCEPTION(ServerException, BadSocketHandle)
}
@@ -215,7 +218,7 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout)
p.fd = mSocketHandle;
p.events = POLLIN;
p.revents = 0;
- switch(::poll(&p, 1, (Timeout == IOStream::TimeOutInfinite)?INFTIM:Timeout))
+ switch(::poll(&p, 1, PollTimeout(Timeout)))
{
case -1:
// error
@@ -275,6 +278,43 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout)
return r;
}
+bool SocketStream::Poll(short Events, int Timeout)
+{
+ // Wait for data to send.
+ struct pollfd p;
+ p.fd = GetSocketHandle();
+ p.events = Events;
+ p.revents = 0;
+
+ box_time_t start = GetCurrentBoxTime();
+ box_time_t end = start + MilliSecondsToBoxTime(Timeout);
+ int result;
+
+ do
+ {
+ box_time_t now = GetCurrentBoxTime();
+ result = ::poll(&p, 1, PollTimeout(end - now));
+ }
+ while(result == -1 && errno == EINTR);
+
+ switch(result)
+ {
+ case -1:
+ // error - Bad!
+ THROW_SYS_ERROR("Failed to poll socket", ServerException,
+ SocketPollError);
+ break;
+
+ case 0:
+ // Condition not met, timed out
+ return false;
+
+ default:
+ // good to go!
+ return true;
+ }
+}
+
// --------------------------------------------------------------------------
//
// Function
@@ -283,7 +323,7 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout)
// Created: 2003/07/31
//
// --------------------------------------------------------------------------
-void SocketStream::Write(const void *pBuffer, int NBytes)
+void SocketStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
if(mSocketHandle == INVALID_SOCKET_VALUE)
{
@@ -296,7 +336,9 @@ void SocketStream::Write(const void *pBuffer, int NBytes)
// Bytes left to send
int bytesLeft = NBytes;
-
+ box_time_t start = GetCurrentBoxTime();
+ box_time_t end = start + MilliSecondsToBoxTime(Timeout);
+
while(bytesLeft > 0)
{
// Try to send.
@@ -327,23 +369,15 @@ void SocketStream::Write(const void *pBuffer, int NBytes)
BOX_TRACE("Waiting to send data on socket " <<
mSocketHandle << " (" << bytesLeft <<
" of " << NBytes << " bytes left)");
-
- // Wait for data to send.
- struct pollfd p;
- p.fd = mSocketHandle;
- p.events = POLLOUT;
- p.revents = 0;
-
- if(::poll(&p, 1, 16000 /* 16 seconds */) == -1)
+
+ box_time_t now = GetCurrentBoxTime();
+
+ if(!Poll(POLLOUT, PollTimeout(end - now)))
{
- // Don't exception if it's just a signal
- if(errno != EINTR)
- {
- BOX_LOG_SYS_ERROR("Failed to poll "
- "socket");
- THROW_EXCEPTION(ServerException,
- SocketPollError)
- }
+ THROW_EXCEPTION_MESSAGE(ConnectionException,
+ Protocol_Timeout, "Timed out waiting "
+ "to send " << bytesLeft << " of " <<
+ NBytes << " bytes");
}
}
}
@@ -514,3 +548,11 @@ bool SocketStream::GetPeerCredentials(uid_t &rUidOut, gid_t &rGidOut)
return false;
}
+void SocketStream::CheckForMissingTimeout(int Timeout)
+{
+ if (Timeout == IOStream::TimeOutInfinite)
+ {
+ BOX_WARNING("Network operation started with no timeout!");
+ DumpStackBacktrace();
+ }
+}
diff --git a/lib/server/SocketStream.h b/lib/server/SocketStream.h
index 2fb5e391..406d29e4 100644
--- a/lib/server/SocketStream.h
+++ b/lib/server/SocketStream.h
@@ -10,6 +10,9 @@
#ifndef SOCKETSTREAM__H
#define SOCKETSTREAM__H
+#include <climits>
+
+#include "BoxTime.h"
#include "IOStream.h"
#include "Socket.h"
@@ -41,7 +44,8 @@ public:
void Attach(int socket);
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual void Close();
virtual bool StreamDataLeft();
virtual bool StreamClosed();
@@ -53,6 +57,24 @@ public:
protected:
void MarkAsReadClosed() {mReadClosed = true;}
void MarkAsWriteClosed() {mWriteClosed = true;}
+ void CheckForMissingTimeout(int Timeout);
+
+ int PollTimeout(box_time_t Timeout)
+ {
+ if (Timeout < 0)
+ {
+ return 0;
+ }
+ else if (Timeout == IOStream::TimeOutInfinite || Timeout > INT_MAX)
+ {
+ return INFTIM;
+ }
+ else
+ {
+ return (int) Timeout;
+ }
+ }
+ bool Poll(short Events, int Timeout);
private:
tOSSocketHandle mSocketHandle;
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)}
diff --git a/lib/server/SocketStreamTLS.h b/lib/server/SocketStreamTLS.h
index bb40ed10..3fda98c1 100644
--- a/lib/server/SocketStreamTLS.h
+++ b/lib/server/SocketStreamTLS.h
@@ -43,7 +43,8 @@ public:
void Handshake(const TLSContext &rContext, bool IsServer = false);
virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
- virtual void Write(const void *pBuffer, int NBytes);
+ virtual void Write(const void *pBuffer, int NBytes,
+ int Timeout = IOStream::TimeOutInfinite);
virtual void Close();
virtual void Shutdown(bool Read = true, bool Write = true);