OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/memory/shared_memory_helper.h" |
| 6 |
| 7 #include "base/threading/thread_restrictions.h" |
| 8 |
| 9 namespace base { |
| 10 |
| 11 #if !defined(OS_ANDROID) |
| 12 bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, |
| 13 ScopedFILE* fp, |
| 14 ScopedFD* readonly_fd, |
| 15 FilePath* path) { |
| 16 #if !(defined(OS_MACOSX) && !defined(OS_IOS)) |
| 17 // It doesn't make sense to have a open-existing private piece of shmem |
| 18 DCHECK(!options.open_existing_deprecated); |
| 19 #endif // !(defined(OS_MACOSX) && !defined(OS_IOS) |
| 20 // Q: Why not use the shm_open() etc. APIs? |
| 21 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
| 22 FilePath directory; |
| 23 ScopedPathUnlinker path_unlinker; |
| 24 if (GetShmemTempDir(options.executable, &directory)) { |
| 25 fp->reset(base::CreateAndOpenTemporaryFileInDir(directory, path)); |
| 26 |
| 27 // Deleting the file prevents anyone else from mapping it in (making it |
| 28 // private), and prevents the need for cleanup (once the last fd is |
| 29 // closed, it is truly freed). |
| 30 if (*fp) |
| 31 path_unlinker.reset(path); |
| 32 } |
| 33 |
| 34 if (*fp) { |
| 35 if (options.share_read_only) { |
| 36 // Also open as readonly so that we can ShareReadOnlyToProcess. |
| 37 readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY))); |
| 38 if (!readonly_fd->is_valid()) { |
| 39 DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; |
| 40 fp->reset(); |
| 41 return false; |
| 42 } |
| 43 } |
| 44 } |
| 45 return true; |
| 46 } |
| 47 |
| 48 bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd, int* mapped_file, |
| 49 int* readonly_mapped_file) { |
| 50 DCHECK_EQ(-1, *mapped_file); |
| 51 DCHECK_EQ(-1, *readonly_mapped_file); |
| 52 if (fp == NULL) |
| 53 return false; |
| 54 |
| 55 // This function theoretically can block on the disk, but realistically |
| 56 // the temporary files we create will just go into the buffer cache |
| 57 // and be deleted before they ever make it out to disk. |
| 58 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 59 |
| 60 struct stat st = {}; |
| 61 if (fstat(fileno(fp.get()), &st)) |
| 62 NOTREACHED(); |
| 63 if (readonly_fd.is_valid()) { |
| 64 struct stat readonly_st = {}; |
| 65 if (fstat(readonly_fd.get(), &readonly_st)) |
| 66 NOTREACHED(); |
| 67 if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { |
| 68 LOG(ERROR) << "writable and read-only inodes don't match; bailing"; |
| 69 return false; |
| 70 } |
| 71 } |
| 72 |
| 73 *mapped_file = HANDLE_EINTR(dup(fileno(fp.get()))); |
| 74 if (*mapped_file == -1) { |
| 75 if (errno == EMFILE) { |
| 76 LOG(WARNING) << "Shared memory creation failed; out of file descriptors"; |
| 77 return false; |
| 78 } else { |
| 79 NOTREACHED() << "Call to dup failed, errno=" << errno; |
| 80 } |
| 81 } |
| 82 *readonly_mapped_file = readonly_fd.release(); |
| 83 |
| 84 return true; |
| 85 } |
| 86 #endif // !defined(OS_ANDROID) |
| 87 |
| 88 } // namespace base |
OLD | NEW |