Index: base/memory/shared_memory_posix.cc |
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc |
index d6c290fa01617581afbaac2a442f7cadc92464a0..35d746e5394e0e042bbaac33421d94c8406e65e2 100644 |
--- a/base/memory/shared_memory_posix.cc |
+++ b/base/memory/shared_memory_posix.cc |
@@ -15,9 +15,11 @@ |
#include "base/files/scoped_file.h" |
#include "base/lazy_instance.h" |
#include "base/logging.h" |
+#include "base/posix/eintr_wrapper.h" |
+#include "base/posix/safe_strerror.h" |
#include "base/process/process_metrics.h" |
#include "base/profiler/scoped_tracker.h" |
-#include "base/safe_strerror_posix.h" |
+#include "base/scoped_generic.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/synchronization/lock.h" |
#include "base/threading/platform_thread.h" |
@@ -38,12 +40,78 @@ namespace { |
LazyInstance<Lock>::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER; |
+struct ScopedPathUnlinkerTraits { |
+ static FilePath* InvalidValue() { return nullptr; } |
+ |
+ static void Free(FilePath* path) { |
+ // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 |
+ // is fixed. |
+ tracked_objects::ScopedTracker tracking_profile( |
+ FROM_HERE_WITH_EXPLICIT_FUNCTION( |
+ "466437 SharedMemory::Create::Unlink")); |
+ if (unlink(path->value().c_str())) |
+ PLOG(WARNING) << "unlink"; |
+ } |
+}; |
+ |
+// Unlinks the FilePath when the object is destroyed. |
+typedef ScopedGeneric<FilePath*, ScopedPathUnlinkerTraits> ScopedPathUnlinker; |
+ |
+#if !defined(OS_ANDROID) |
+// Makes a temporary file, fdopens it, and then unlinks it. |fp| is populated |
+// with the fdopened FILE. |readonly_fd| is populated with the opened fd if |
+// options.share_read_only is true. |path| is populated with the location of |
+// the file before it was unlinked. |
+// Returns false if there's an unhandled failure. |
+bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, |
+ ScopedFILE* fp, |
+ ScopedFD* readonly_fd, |
+ FilePath* path) { |
+ // It doesn't make sense to have a open-existing private piece of shmem |
+ DCHECK(!options.open_existing_deprecated); |
+ // Q: Why not use the shm_open() etc. APIs? |
+ // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
+ FilePath directory; |
+ ScopedPathUnlinker path_unlinker; |
+ if (GetShmemTempDir(options.executable, &directory)) { |
+ // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 |
+ // is fixed. |
+ tracked_objects::ScopedTracker tracking_profile( |
+ FROM_HERE_WITH_EXPLICIT_FUNCTION( |
+ "466437 SharedMemory::Create::OpenTemporaryFile")); |
+ fp->reset(base::CreateAndOpenTemporaryFileInDir(directory, path)); |
+ |
+ // Deleting the file prevents anyone else from mapping it in (making it |
+ // private), and prevents the need for cleanup (once the last fd is |
+ // closed, it is truly freed). |
+ if (*fp) |
+ path_unlinker.reset(path); |
+ } |
+ |
+ if (*fp) { |
+ if (options.share_read_only) { |
+ // TODO(erikchen): Remove ScopedTracker below once |
+ // http://crbug.com/466437 is fixed. |
+ tracked_objects::ScopedTracker tracking_profile( |
+ FROM_HERE_WITH_EXPLICIT_FUNCTION( |
+ "466437 SharedMemory::Create::OpenReadonly")); |
+ // Also open as readonly so that we can ShareReadOnlyToProcess. |
+ readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY))); |
+ if (!readonly_fd->is_valid()) { |
+ DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; |
+ fp->reset(); |
+ return false; |
+ } |
+ } |
+ } |
+ return true; |
+} |
+#endif // !defined(OS_ANDROID) |
} |
SharedMemory::SharedMemory() |
: mapped_file_(-1), |
readonly_mapped_file_(-1), |
- inode_(0), |
mapped_size_(0), |
memory_(NULL), |
read_only_(false), |
@@ -53,24 +121,16 @@ SharedMemory::SharedMemory() |
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) |
: mapped_file_(handle.fd), |
readonly_mapped_file_(-1), |
- inode_(0), |
mapped_size_(0), |
memory_(NULL), |
read_only_(read_only), |
requested_size_(0) { |
- struct stat st; |
- if (fstat(handle.fd, &st) == 0) { |
- // If fstat fails, then the file descriptor is invalid and we'll learn this |
- // fact when Map() fails. |
- inode_ = st.st_ino; |
- } |
} |
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, |
ProcessHandle process) |
: mapped_file_(handle.fd), |
readonly_mapped_file_(-1), |
- inode_(0), |
mapped_size_(0), |
memory_(NULL), |
read_only_(read_only), |
@@ -107,11 +167,35 @@ size_t SharedMemory::GetHandleLimit() { |
return base::GetMaxFds(); |
} |
+// static |
+SharedMemoryHandle SharedMemory::DuplicateHandle( |
+ const SharedMemoryHandle& handle) { |
+ int duped_handle = HANDLE_EINTR(dup(handle.fd)); |
+ if (duped_handle < 0) |
+ return base::SharedMemory::NULLHandle(); |
+ return base::FileDescriptor(duped_handle, true); |
+} |
+ |
+// static |
+int SharedMemory::GetFdFromSharedMemoryHandle( |
+ const SharedMemoryHandle& handle) { |
+ return handle.fd; |
+} |
+ |
bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
return CreateAnonymous(size) && Map(size); |
} |
#if !defined(OS_ANDROID) |
+// static |
+int SharedMemory::GetSizeFromSharedMemoryHandle( |
+ const SharedMemoryHandle& handle) { |
+ struct stat st; |
+ if (fstat(handle.fd, &st) != 0) |
+ return -1; |
+ return st.st_size; |
+} |
+ |
// Chromium mostly only uses the unique/private shmem as specified by |
// "name == L"". The exception is in the StatsTable. |
// TODO(jrg): there is no way to "clean up" all unused named shmem if |
@@ -141,47 +225,10 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
FilePath path; |
if (options.name_deprecated == NULL || options.name_deprecated->empty()) { |
- // It doesn't make sense to have a open-existing private piece of shmem |
- DCHECK(!options.open_existing_deprecated); |
- // Q: Why not use the shm_open() etc. APIs? |
- // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
- FilePath directory; |
- if (GetShmemTempDir(options.executable, &directory)) { |
- // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 |
- // is fixed. |
- tracked_objects::ScopedTracker tracking_profile2( |
- FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466437 SharedMemory::Create::OpenTemporaryFile")); |
- fp.reset(CreateAndOpenTemporaryFileInDir(directory, &path)); |
- } |
- |
- if (fp) { |
- if (options.share_read_only) { |
- // TODO(erikchen): Remove ScopedTracker below once |
- // http://crbug.com/466437 is fixed. |
- tracked_objects::ScopedTracker tracking_profile3( |
- FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466437 SharedMemory::Create::OpenReadonly")); |
- // Also open as readonly so that we can ShareReadOnlyToProcess. |
- readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); |
- if (!readonly_fd.is_valid()) { |
- DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; |
- fp.reset(); |
- return false; |
- } |
- } |
- |
- // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 |
- // is fixed. |
- tracked_objects::ScopedTracker tracking_profile4( |
- FROM_HERE_WITH_EXPLICIT_FUNCTION( |
- "466437 SharedMemory::Create::Unlink")); |
- // Deleting the file prevents anyone else from mapping it in (making it |
- // private), and prevents the need for cleanup (once the last fd is |
- // closed, it is truly freed). |
- if (unlink(path.value().c_str())) |
- PLOG(WARNING) << "unlink"; |
- } |
+ bool result = |
+ CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); |
+ if (!result) |
+ return false; |
} else { |
if (!FilePathForMemoryName(*options.name_deprecated, &path)) |
return false; |
@@ -402,7 +449,7 @@ bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { |
} |
} |
- mapped_file_ = dup(fileno(fp.get())); |
+ mapped_file_ = HANDLE_EINTR(dup(fileno(fp.get()))); |
if (mapped_file_ == -1) { |
if (errno == EMFILE) { |
LOG(WARNING) << "Shared memory creation failed; out of file descriptors"; |
@@ -411,7 +458,6 @@ bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { |
NOTREACHED() << "Call to dup failed, errno=" << errno; |
} |
} |
- inode_ = st.st_ino; |
readonly_mapped_file_ = readonly_fd.release(); |
return true; |
@@ -459,7 +505,7 @@ void SharedMemory::LockOrUnlockCommon(int function) { |
<< " function:" << function |
<< " fd:" << mapped_file_ |
<< " errno:" << errno |
- << " msg:" << safe_strerror(errno); |
+ << " msg:" << base::safe_strerror(errno); |
} |
} |
} |
@@ -481,7 +527,7 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process, |
break; |
} |
- const int new_fd = dup(handle_to_dup); |
+ const int new_fd = HANDLE_EINTR(dup(handle_to_dup)); |
if (new_fd < 0) { |
DPLOG(ERROR) << "dup() failed."; |
return false; |