| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/shared_memory.h" | 5 #include "base/shared_memory.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <sys/mman.h> | 9 #include <sys/mman.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { | 91 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { |
| 92 DCHECK_GE(handle.fd, 0); | 92 DCHECK_GE(handle.fd, 0); |
| 93 if (HANDLE_EINTR(close(handle.fd)) < 0) | 93 if (HANDLE_EINTR(close(handle.fd)) < 0) |
| 94 DPLOG(ERROR) << "close"; | 94 DPLOG(ERROR) << "close"; |
| 95 } | 95 } |
| 96 | 96 |
| 97 bool SharedMemory::CreateAndMapAnonymous(uint32 size) { | 97 bool SharedMemory::CreateAndMapAnonymous(uint32 size) { |
| 98 return CreateAnonymous(size) && Map(size); | 98 return CreateAnonymous(size) && Map(size); |
| 99 } | 99 } |
| 100 | 100 |
| 101 bool SharedMemory::CreateAnonymous(uint32 size) { | |
| 102 return CreateNamed("", false, size); | |
| 103 } | |
| 104 | |
| 105 #if !defined(OS_ANDROID) | 101 #if !defined(OS_ANDROID) |
| 106 // Chromium mostly only uses the unique/private shmem as specified by | 102 // Chromium mostly only uses the unique/private shmem as specified by |
| 107 // "name == L"". The exception is in the StatsTable. | 103 // "name == L"". The exception is in the StatsTable. |
| 108 // TODO(jrg): there is no way to "clean up" all unused named shmem if | 104 // TODO(jrg): there is no way to "clean up" all unused named shmem if |
| 109 // we restart from a crash. (That isn't a new problem, but it is a problem.) | 105 // we restart from a crash. (That isn't a new problem, but it is a problem.) |
| 110 // In case we want to delete it later, it may be useful to save the value | 106 // In case we want to delete it later, it may be useful to save the value |
| 111 // of mem_filename after FilePathForMemoryName(). | 107 // of mem_filename after FilePathForMemoryName(). |
| 112 bool SharedMemory::CreateNamed(const std::string& name, | 108 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
| 113 bool open_existing, uint32 size) { | |
| 114 DCHECK_EQ(-1, mapped_file_); | 109 DCHECK_EQ(-1, mapped_file_); |
| 115 if (size == 0) return false; | 110 if (options.size == 0) return false; |
| 116 | 111 |
| 117 // This function theoretically can block on the disk, but realistically | 112 // This function theoretically can block on the disk, but realistically |
| 118 // the temporary files we create will just go into the buffer cache | 113 // the temporary files we create will just go into the buffer cache |
| 119 // and be deleted before they ever make it out to disk. | 114 // and be deleted before they ever make it out to disk. |
| 120 base::ThreadRestrictions::ScopedAllowIO allow_io; | 115 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 121 | 116 |
| 122 FILE *fp; | 117 FILE *fp; |
| 123 bool fix_size = true; | 118 bool fix_size = true; |
| 124 | 119 |
| 125 FilePath path; | 120 FilePath path; |
| 126 if (name.empty()) { | 121 if (options.name == NULL || options.name->empty()) { |
| 127 // It doesn't make sense to have a open-existing private piece of shmem | 122 // It doesn't make sense to have a open-existing private piece of shmem |
| 128 DCHECK(!open_existing); | 123 DCHECK(!options.open_existing); |
| 129 // Q: Why not use the shm_open() etc. APIs? | 124 // Q: Why not use the shm_open() etc. APIs? |
| 130 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU | 125 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
| 131 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); | 126 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); |
| 132 | 127 |
| 133 // Deleting the file prevents anyone else from mapping it in | 128 // Deleting the file prevents anyone else from mapping it in |
| 134 // (making it private), and prevents the need for cleanup (once | 129 // (making it private), and prevents the need for cleanup (once |
| 135 // the last fd is closed, it is truly freed). | 130 // the last fd is closed, it is truly freed). |
| 136 if (fp) | 131 if (fp) |
| 137 file_util::Delete(path, false); | 132 file_util::Delete(path, false); |
| 138 | 133 |
| 139 } else { | 134 } else { |
| 140 if (!FilePathForMemoryName(name, &path)) | 135 if (!FilePathForMemoryName(*options.name, &path)) |
| 141 return false; | 136 return false; |
| 142 | 137 |
| 143 fp = file_util::OpenFile(path, "w+x"); | 138 fp = file_util::OpenFile(path, "w+x"); |
| 144 if (fp == NULL && open_existing) { | 139 if (fp == NULL && options.open_existing) { |
| 145 // "w+" will truncate if it already exists. | 140 // "w+" will truncate if it already exists. |
| 146 fp = file_util::OpenFile(path, "a+"); | 141 fp = file_util::OpenFile(path, "a+"); |
| 147 fix_size = false; | 142 fix_size = false; |
| 148 } | 143 } |
| 149 } | 144 } |
| 150 if (fp && fix_size) { | 145 if (fp && fix_size) { |
| 151 // Get current size. | 146 // Get current size. |
| 152 struct stat stat; | 147 struct stat stat; |
| 153 if (fstat(fileno(fp), &stat) != 0) { | 148 if (fstat(fileno(fp), &stat) != 0) { |
| 154 file_util::CloseFile(fp); | 149 file_util::CloseFile(fp); |
| 155 return false; | 150 return false; |
| 156 } | 151 } |
| 157 const uint32 current_size = stat.st_size; | 152 const uint32 current_size = stat.st_size; |
| 158 if (current_size != size) { | 153 if (current_size != options.size) { |
| 159 if (HANDLE_EINTR(ftruncate(fileno(fp), size)) != 0) { | 154 if (HANDLE_EINTR(ftruncate(fileno(fp), options.size)) != 0) { |
| 160 file_util::CloseFile(fp); | 155 file_util::CloseFile(fp); |
| 161 return false; | 156 return false; |
| 162 } | 157 } |
| 163 if (fseeko(fp, size, SEEK_SET) != 0) { | 158 if (fseeko(fp, options.size, SEEK_SET) != 0) { |
| 164 file_util::CloseFile(fp); | 159 file_util::CloseFile(fp); |
| 165 return false; | 160 return false; |
| 166 } | 161 } |
| 167 } | 162 } |
| 168 created_size_ = size; | 163 created_size_ = options.size; |
| 169 } | 164 } |
| 170 if (fp == NULL) { | 165 if (fp == NULL) { |
| 171 #if !defined(OS_MACOSX) | 166 #if !defined(OS_MACOSX) |
| 172 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; | 167 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; |
| 173 FilePath dir = path.DirName(); | 168 FilePath dir = path.DirName(); |
| 174 if (access(dir.value().c_str(), W_OK | X_OK) < 0) { | 169 if (access(dir.value().c_str(), W_OK | X_OK) < 0) { |
| 175 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); | 170 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); |
| 176 if (dir.value() == "/dev/shm") { | 171 if (dir.value() == "/dev/shm") { |
| 177 LOG(FATAL) << "This is frequently caused by incorrect permissions on " | 172 LOG(FATAL) << "This is frequently caused by incorrect permissions on " |
| 178 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; | 173 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 new_handle->fd = new_fd; | 360 new_handle->fd = new_fd; |
| 366 new_handle->auto_close = true; | 361 new_handle->auto_close = true; |
| 367 | 362 |
| 368 if (close_self) | 363 if (close_self) |
| 369 Close(); | 364 Close(); |
| 370 | 365 |
| 371 return true; | 366 return true; |
| 372 } | 367 } |
| 373 | 368 |
| 374 } // namespace base | 369 } // namespace base |
| OLD | NEW |