Index: base/memory/shared_memory_helper.cc |
diff --git a/base/memory/shared_memory_helper.cc b/base/memory/shared_memory_helper.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bcef74a6cb231159c859c39c66a3209dfd815f01 |
--- /dev/null |
+++ b/base/memory/shared_memory_helper.cc |
@@ -0,0 +1,88 @@ |
+// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
Alexei Svitkine (slow)
2016/12/09 18:04:15
Nit: No (c)
lawrencewu
2016/12/09 18:33:57
Done.
|
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/memory/shared_memory_helper.h" |
+ |
+#include "base/threading/thread_restrictions.h" |
+ |
+namespace base { |
+ |
+#if !defined(OS_ANDROID) |
+bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, |
+ ScopedFILE* fp, |
+ ScopedFD* readonly_fd, |
+ FilePath* path) { |
+#if !(defined(OS_MACOSX) && !defined(OS_IOS)) |
+ // It doesn't make sense to have a open-existing private piece of shmem |
+ DCHECK(!options.open_existing_deprecated); |
+#endif // !(defined(OS_MACOSX) && !defined(OS_IOS) |
+ // 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)) { |
+ 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) { |
Alexei Svitkine (slow)
2016/12/09 18:04:15
Nit: Combine with the above if.
lawrencewu
2016/12/09 18:33:57
Done.
|
+ // 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; |
+} |
+ |
+bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd, int* mapped_file, |
+ int* readonly_mapped_file) { |
+ DCHECK_EQ(-1, *mapped_file); |
+ DCHECK_EQ(-1, *readonly_mapped_file); |
+ if (fp == NULL) |
+ return false; |
+ |
+ // This function theoretically can block on the disk, but realistically |
+ // the temporary files we create will just go into the buffer cache |
+ // and be deleted before they ever make it out to disk. |
+ base::ThreadRestrictions::ScopedAllowIO allow_io; |
+ |
+ struct stat st = {}; |
+ if (fstat(fileno(fp.get()), &st)) |
+ NOTREACHED(); |
+ if (readonly_fd.is_valid()) { |
+ struct stat readonly_st = {}; |
+ if (fstat(readonly_fd.get(), &readonly_st)) |
+ NOTREACHED(); |
+ if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { |
+ LOG(ERROR) << "writable and read-only inodes don't match; bailing"; |
+ return false; |
+ } |
+ } |
+ |
+ *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"; |
+ return false; |
+ } else { |
Alexei Svitkine (slow)
2016/12/09 18:04:15
Nit: No else since you return above.
lawrencewu
2016/12/09 18:33:57
Done.
|
+ NOTREACHED() << "Call to dup failed, errno=" << errno; |
+ } |
+ } |
+ *readonly_mapped_file = readonly_fd.release(); |
+ |
+ return true; |
+} |
+#endif // !defined(OS_ANDROID) |
+ |
+} // namespace base |