Index: mojo/system/raw_channel_posix.cc |
diff --git a/mojo/system/raw_channel_posix.cc b/mojo/system/raw_channel_posix.cc |
index d50ff8b3cddc24ea7d76dfdb85ab33c4b5b2e278..64f46c636285e65a7c9028f2708ef2bac5e0af03 100644 |
--- a/mojo/system/raw_channel_posix.cc |
+++ b/mojo/system/raw_channel_posix.cc |
@@ -9,6 +9,7 @@ |
#include <unistd.h> |
#include <algorithm> |
+#include <deque> |
#include "base/basictypes.h" |
#include "base/bind.h" |
@@ -68,7 +69,7 @@ class RawChannelPosix : public RawChannel, |
bool pending_read_; |
- embedder::ScopedPlatformHandleVectorPtr read_platform_handles_; |
+ std::deque<embedder::PlatformHandle> read_platform_handles_; |
// The following members are used on multiple threads and protected by |
// |write_lock()|: |
@@ -102,6 +103,8 @@ RawChannelPosix::~RawChannelPosix() { |
// These must have been shut down/destroyed on the I/O thread. |
DCHECK(!read_watcher_.get()); |
DCHECK(!write_watcher_.get()); |
+ |
+ embedder::CloseAllPlatformHandles(&read_platform_handles_); |
} |
size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { |
@@ -117,23 +120,31 @@ RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { |
size_t bytes_to_read = 0; |
read_buffer()->GetBuffer(&buffer, &bytes_to_read); |
- size_t old_num_platform_handles = |
- read_platform_handles_ ? read_platform_handles_->size() : 0; |
+ size_t old_num_platform_handles = read_platform_handles_.size(); |
ssize_t read_result = |
embedder::PlatformChannelRecvmsg(fd_.get(), |
buffer, |
bytes_to_read, |
&read_platform_handles_); |
- if (read_platform_handles_ && |
- read_platform_handles_->size() > old_num_platform_handles) { |
+ if (read_platform_handles_.size() > old_num_platform_handles) { |
+ DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, |
+ embedder::kPlatformChannelMaxNumHandles); |
+ |
if (read_result != 1) { |
LOG(WARNING) << "Invalid control message with platform handles"; |
return IO_FAILED; |
} |
- if (read_platform_handles_->size() > TransportData::kMaxPlatformHandles) { |
+ // We should never accumulate more than |TransportData::kMaxPlatformHandles |
+ // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is |
+ // possible because we could have accumulated all the handles for a message, |
+ // then received the message data plus the first set of handles for the next |
+ // message in the subsequent |recvmsg()|.) |
+ if (read_platform_handles_.size() > (TransportData::kMaxPlatformHandles + |
+ embedder::kPlatformChannelMaxNumHandles)) { |
LOG(WARNING) << "Received too many platform handles"; |
- read_platform_handles_.reset(); |
+ embedder::CloseAllPlatformHandles(&read_platform_handles_); |
+ read_platform_handles_.clear(); |
return IO_FAILED; |
} |
@@ -173,13 +184,20 @@ embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( |
const void* /*platform_handle_table*/) { |
DCHECK_GT(num_platform_handles, 0u); |
- if (!read_platform_handles_ || |
- read_platform_handles_->size() != num_platform_handles) { |
- read_platform_handles_.reset(); |
+ if (read_platform_handles_.size() < num_platform_handles) { |
+ embedder::CloseAllPlatformHandles(&read_platform_handles_); |
+ read_platform_handles_.clear(); |
return embedder::ScopedPlatformHandleVectorPtr(); |
} |
- return read_platform_handles_.Pass(); |
+ embedder::ScopedPlatformHandleVectorPtr rv( |
+ new embedder::PlatformHandleVector(num_platform_handles)); |
+ rv->assign(read_platform_handles_.begin(), |
+ read_platform_handles_.begin() + num_platform_handles); |
+ read_platform_handles_.erase( |
+ read_platform_handles_.begin(), |
+ read_platform_handles_.begin() + num_platform_handles); |
+ return rv.Pass(); |
} |
RawChannel::IOResult RawChannelPosix::WriteNoLock( |