Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Unified Diff: ipc/file_descriptor_set_posix.cc

Issue 583473002: IPC: Get rid of FileDescriptor usage from FileDescriptorSet and Message (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ipc/file_descriptor_set_posix.cc
diff --git a/ipc/file_descriptor_set_posix.cc b/ipc/file_descriptor_set_posix.cc
index 1aa86a7f0084ea41ae55435affe7cd014ce3dc6f..b6bf451779f90dd7f67ed6fa6c1c1e3386505966 100644
--- a/ipc/file_descriptor_set_posix.cc
+++ b/ipc/file_descriptor_set_posix.cc
@@ -16,55 +16,48 @@ FileDescriptorSet::FileDescriptorSet()
}
FileDescriptorSet::~FileDescriptorSet() {
- if (consumed_descriptor_highwater_ == descriptors_.size())
+ if (consumed_descriptor_highwater_ == size())
return;
- LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors";
- // We close all the descriptors where the close flag is set. If this
- // message should have been transmitted, then closing those with close
- // flags set mirrors the expected behaviour.
+ // We close all the owning descriptors. If this message should have
+ // been transmitted, then closing those with close flags set mirrors
+ // the expected behaviour.
//
// If this message was received with more descriptors than expected
// (which could a DOS against the browser by a rogue renderer) then all
// the descriptors have their close flag set and we free all the extra
// kernel resources.
- for (unsigned i = consumed_descriptor_highwater_;
- i < descriptors_.size(); ++i) {
- if (descriptors_[i].auto_close)
- if (IGNORE_EINTR(close(descriptors_[i].fd)) < 0)
- PLOG(ERROR) << "close";
- }
+ LOG(WARNING) << "FileDescriptorSet destroyed with unconsumed descriptors: "
+ << consumed_descriptor_highwater_ << "/" << size();
}
-bool FileDescriptorSet::Add(int fd) {
- if (descriptors_.size() == kMaxDescriptorsPerMessage) {
+bool FileDescriptorSet::AddToBorrow(base::PlatformFile fd) {
+ DCHECK_EQ(consumed_descriptor_highwater_, 0u);
+
+ if (size() == kMaxDescriptorsPerMessage) {
DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full.";
return false;
}
- struct base::FileDescriptor sd;
- sd.fd = fd;
- sd.auto_close = false;
- descriptors_.push_back(sd);
+ borrowed_descriptors_.push_back(fd);
return true;
}
-bool FileDescriptorSet::AddAndAutoClose(int fd) {
- if (descriptors_.size() == kMaxDescriptorsPerMessage) {
+bool FileDescriptorSet::AddToOwn(base::File fd) {
+ DCHECK_EQ(consumed_descriptor_highwater_, 0u);
+
+ if (size() == kMaxDescriptorsPerMessage) {
DLOG(WARNING) << "Cannot add file descriptor. FileDescriptorSet full.";
return false;
}
- struct base::FileDescriptor sd;
- sd.fd = fd;
- sd.auto_close = true;
- descriptors_.push_back(sd);
- DCHECK(descriptors_.size() <= kMaxDescriptorsPerMessage);
+ owned_descriptors_.push_back(new base::File(fd.Pass()));
+ DCHECK(size() <= kMaxDescriptorsPerMessage);
return true;
}
-int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
- if (index >= descriptors_.size())
+base::PlatformFile FileDescriptorSet::TakeDescriptorAt(unsigned index) {
+ if (index >= size())
return -1;
// We should always walk the descriptors in order, so it's reasonable to
@@ -83,32 +76,55 @@ int FileDescriptorSet::GetDescriptorAt(unsigned index) const {
// So we can either track of the use of each descriptor in a bitset, or we
// can enforce that we walk the indexes strictly in order.
//
- // There's one more wrinkle: When logging messages, we may reparse them. So
agl 2014/09/18 01:17:26 If you're removing this (is that safe?) then the c
Hajime Morrita 2014/09/18 01:29:08 Done.
- // we have an exception: When the consumed_descriptor_highwater_ is at the
- // end of the array and index 0 is requested, we reset the highwater value.
- if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size())
- consumed_descriptor_highwater_ = 0;
-
if (index != consumed_descriptor_highwater_)
return -1;
consumed_descriptor_highwater_ = index + 1;
- return descriptors_[index].fd;
+
+ if (index < owned_descriptors_.size())
+ return owned_descriptors_[index]->TakePlatformFile();
+
+ // TODO(morrita): This only happens with unit tests and should never
+ // be hit in production as all deserialized descriptors are owned by
+ // IPC::Message. Once there is no borrowed descriptors being taken,
+ // we can return File instead of PlatformFile here. Also see TODOs
+ // in file_descriptor_set_posix_unittest.cc
+ base::PlatformFile file =
+ borrowed_descriptors_[index - owned_descriptors_.size()];
+ borrowed_descriptors_[index - owned_descriptors_.size()] = -1;
+ return file;
}
void FileDescriptorSet::GetDescriptors(int* buffer) const {
- for (std::vector<base::FileDescriptor>::const_iterator
- i = descriptors_.begin(); i != descriptors_.end(); ++i) {
- *(buffer++) = i->fd;
+ for (ScopedVector<base::File>::const_iterator i = owned_descriptors_.begin();
+ i != owned_descriptors_.end();
+ ++i) {
+ *(buffer++) = (*i)->GetPlatformFile();
+ }
+
+ for (std::vector<base::PlatformFile>::const_iterator i =
+ borrowed_descriptors_.begin();
+ i != borrowed_descriptors_.end();
+ ++i) {
+ *(buffer++) = *i;
}
}
bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
struct stat st;
- for (std::vector<base::FileDescriptor>::const_iterator
- i = descriptors_.begin(); i != descriptors_.end(); ++i) {
- if (fstat(i->fd, &st) == 0 && S_ISDIR(st.st_mode))
+ for (ScopedVector<base::File>::const_iterator i = owned_descriptors_.begin();
+ i != owned_descriptors_.end();
+ ++i) {
+ if (fstat((*i)->GetPlatformFile(), &st) == 0 && S_ISDIR(st.st_mode))
+ return true;
+ }
+
+ for (std::vector<base::PlatformFile>::const_iterator i =
+ borrowed_descriptors_.begin();
+ i != borrowed_descriptors_.end();
+ ++i) {
+ if (fstat(*i, &st) == 0 && S_ISDIR(st.st_mode))
return true;
}
@@ -116,36 +132,28 @@ bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
}
void FileDescriptorSet::CommitAll() {
- for (std::vector<base::FileDescriptor>::iterator
- i = descriptors_.begin(); i != descriptors_.end(); ++i) {
- if (i->auto_close)
- if (IGNORE_EINTR(close(i->fd)) < 0)
- PLOG(ERROR) << "close";
- }
- descriptors_.clear();
+ owned_descriptors_.clear();
+ borrowed_descriptors_.clear();
consumed_descriptor_highwater_ = 0;
}
-void FileDescriptorSet::ReleaseFDsToClose(std::vector<int>* fds) {
- for (std::vector<base::FileDescriptor>::iterator
- i = descriptors_.begin(); i != descriptors_.end(); ++i) {
- if (i->auto_close)
- fds->push_back(i->fd);
+void FileDescriptorSet::ReleaseFDsToClose(
+ std::vector<base::PlatformFile>* fds) {
+ for (ScopedVector<base::File>::iterator i = owned_descriptors_.begin();
+ i != owned_descriptors_.end();
+ ++i) {
+ fds->push_back((*i)->TakePlatformFile());
}
- descriptors_.clear();
- consumed_descriptor_highwater_ = 0;
+
+ CommitAll();
}
void FileDescriptorSet::SetDescriptors(const int* buffer, unsigned count) {
DCHECK(count <= kMaxDescriptorsPerMessage);
- DCHECK_EQ(descriptors_.size(), 0u);
+ DCHECK_EQ(size(), 0u);
DCHECK_EQ(consumed_descriptor_highwater_, 0u);
- descriptors_.reserve(count);
- for (unsigned i = 0; i < count; ++i) {
- struct base::FileDescriptor sd;
- sd.fd = buffer[i];
- sd.auto_close = true;
- descriptors_.push_back(sd);
- }
+ owned_descriptors_.reserve(count);
+ for (unsigned i = 0; i < count; ++i)
+ owned_descriptors_.push_back(new base::File(buffer[i]));
}

Powered by Google App Engine
This is Rietveld 408576698