| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 return false; | 89 return false; |
| 90 | 90 |
| 91 max_size_ = size; | 91 max_size_ = size; |
| 92 return true; | 92 return true; |
| 93 } | 93 } |
| 94 | 94 |
| 95 // Our current implementation of shmem is with mmap()ing of files. | 95 // Our current implementation of shmem is with mmap()ing of files. |
| 96 // These files need to be deleted explicitly. | 96 // These files need to be deleted explicitly. |
| 97 // In practice this call is only needed for unit tests. | 97 // In practice this call is only needed for unit tests. |
| 98 bool SharedMemory::Delete(const std::wstring& name) { | 98 bool SharedMemory::Delete(const std::wstring& name) { |
| 99 std::wstring mem_filename; | 99 FilePath path; |
| 100 if (FilenameForMemoryName(name, &mem_filename) == false) | 100 if (!FilePathForMemoryName(name, &path)) |
| 101 return false; | 101 return false; |
| 102 | 102 |
| 103 FilePath path(WideToUTF8(mem_filename)); | |
| 104 if (file_util::PathExists(path)) { | 103 if (file_util::PathExists(path)) { |
| 105 return file_util::Delete(path, false); | 104 return file_util::Delete(path, false); |
| 106 } | 105 } |
| 107 | 106 |
| 108 // Doesn't exist, so success. | 107 // Doesn't exist, so success. |
| 109 return true; | 108 return true; |
| 110 } | 109 } |
| 111 | 110 |
| 112 bool SharedMemory::Open(const std::wstring &name, bool read_only) { | 111 bool SharedMemory::Open(const std::wstring &name, bool read_only) { |
| 113 read_only_ = read_only; | 112 read_only_ = read_only; |
| 114 | 113 |
| 115 int posix_flags = 0; | 114 int posix_flags = 0; |
| 116 posix_flags |= read_only ? O_RDONLY : O_RDWR; | 115 posix_flags |= read_only ? O_RDONLY : O_RDWR; |
| 117 | 116 |
| 118 return CreateOrOpen(name, posix_flags, 0); | 117 return CreateOrOpen(name, posix_flags, 0); |
| 119 } | 118 } |
| 120 | 119 |
| 121 // For the given shmem named |memname|, return a filename to mmap() | 120 // For the given shmem named |memname|, return a filename to mmap() |
| 122 // (and possibly create). Modifies |filename|. Return false on | 121 // (and possibly create). Modifies |filename|. Return false on |
| 123 // error, or true of we are happy. | 122 // error, or true of we are happy. |
| 124 bool SharedMemory::FilenameForMemoryName(const std::wstring &memname, | 123 bool SharedMemory::FilePathForMemoryName(const std::wstring& memname, |
| 125 std::wstring *filename) { | 124 FilePath* path) { |
| 126 std::wstring mem_filename; | |
| 127 | |
| 128 // mem_name will be used for a filename; make sure it doesn't | 125 // mem_name will be used for a filename; make sure it doesn't |
| 129 // contain anything which will confuse us. | 126 // contain anything which will confuse us. |
| 130 DCHECK(memname.find_first_of(L"/") == std::string::npos); | 127 DCHECK(memname.find_first_of(L"/") == std::string::npos); |
| 131 DCHECK(memname.find_first_of(L"\0") == std::string::npos); | 128 DCHECK(memname.find_first_of(L"\0") == std::string::npos); |
| 132 | 129 |
| 133 FilePath temp_dir; | 130 FilePath temp_dir; |
| 134 if (file_util::GetShmemTempDir(&temp_dir) == false) | 131 if (file_util::GetShmemTempDir(&temp_dir) == false) |
| 135 return false; | 132 return false; |
| 136 | 133 |
| 137 mem_filename = UTF8ToWide(temp_dir.value()); | 134 *path = temp_dir.AppendASCII("com.google.chrome.shmem." + |
| 138 file_util::AppendToPath(&mem_filename, L"com.google.chrome.shmem." + memname); | 135 WideToASCII(memname)); |
| 139 *filename = mem_filename; | |
| 140 return true; | 136 return true; |
| 141 } | 137 } |
| 142 | 138 |
| 143 // Chromium mostly only use the unique/private shmem as specified by | 139 // Chromium mostly only use the unique/private shmem as specified by |
| 144 // "name == L"". The exception is in the StatsTable. | 140 // "name == L"". The exception is in the StatsTable. |
| 145 // TODO(jrg): there is no way to "clean up" all unused named shmem if | 141 // TODO(jrg): there is no way to "clean up" all unused named shmem if |
| 146 // we restart from a crash. (That isn't a new problem, but it is a problem.) | 142 // we restart from a crash. (That isn't a new problem, but it is a problem.) |
| 147 // In case we want to delete it later, it may be useful to save the value | 143 // In case we want to delete it later, it may be useful to save the value |
| 148 // of mem_filename after FilenameForMemoryName(). | 144 // of mem_filename after FilePathForMemoryName(). |
| 149 bool SharedMemory::CreateOrOpen(const std::wstring &name, | 145 bool SharedMemory::CreateOrOpen(const std::wstring &name, |
| 150 int posix_flags, size_t size) { | 146 int posix_flags, size_t size) { |
| 151 DCHECK(mapped_file_ == -1); | 147 DCHECK(mapped_file_ == -1); |
| 152 | 148 |
| 153 file_util::ScopedFILE file_closer; | 149 file_util::ScopedFILE file_closer; |
| 154 FILE *fp; | 150 FILE *fp; |
| 155 | 151 |
| 152 FilePath path; |
| 156 if (name == L"") { | 153 if (name == L"") { |
| 157 // It doesn't make sense to have a read-only private piece of shmem | 154 // It doesn't make sense to have a read-only private piece of shmem |
| 158 DCHECK(posix_flags & (O_RDWR | O_WRONLY)); | 155 DCHECK(posix_flags & (O_RDWR | O_WRONLY)); |
| 159 | 156 |
| 160 FilePath path; | 157 // Q: Why not use the shm_open() etc. APIs? |
| 158 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
| 161 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); | 159 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); |
| 162 | 160 |
| 163 // Deleting the file prevents anyone else from mapping it in | 161 // Deleting the file prevents anyone else from mapping it in |
| 164 // (making it private), and prevents the need for cleanup (once | 162 // (making it private), and prevents the need for cleanup (once |
| 165 // the last fd is closed, it is truly freed). | 163 // the last fd is closed, it is truly freed). |
| 166 file_util::Delete(path, false); | 164 file_util::Delete(path, false); |
| 167 } else { | 165 } else { |
| 168 std::wstring mem_filename; | 166 if (!FilePathForMemoryName(name, &path)) |
| 169 if (FilenameForMemoryName(name, &mem_filename) == false) | |
| 170 return false; | 167 return false; |
| 171 | 168 |
| 172 std::string mode; | 169 std::string mode; |
| 173 switch (posix_flags) { | 170 switch (posix_flags) { |
| 174 case (O_RDWR | O_CREAT): | 171 case (O_RDWR | O_CREAT): |
| 175 // Careful: "w+" will truncate if it already exists. | 172 // Careful: "w+" will truncate if it already exists. |
| 176 mode = "a+"; | 173 mode = "a+"; |
| 177 break; | 174 break; |
| 178 case O_RDWR: | 175 case O_RDWR: |
| 179 mode = "r+"; | 176 mode = "r+"; |
| 180 break; | 177 break; |
| 181 case O_RDONLY: | 178 case O_RDONLY: |
| 182 mode = "r"; | 179 mode = "r"; |
| 183 break; | 180 break; |
| 184 default: | 181 default: |
| 185 NOTIMPLEMENTED(); | 182 NOTIMPLEMENTED(); |
| 186 break; | 183 break; |
| 187 } | 184 } |
| 188 | 185 |
| 189 fp = file_util::OpenFile(mem_filename, mode.c_str()); | 186 fp = file_util::OpenFile(path, mode.c_str()); |
| 190 } | 187 } |
| 191 | 188 |
| 192 if (fp == NULL) | 189 if (fp == NULL) { |
| 190 if (posix_flags & O_CREAT) |
| 191 LOG(ERROR) << "Creating shared memory in " << path.value() << " failed: " |
| 192 << strerror(errno); |
| 193 return false; | 193 return false; |
| 194 } |
| 195 |
| 194 file_closer.reset(fp); // close when we go out of scope | 196 file_closer.reset(fp); // close when we go out of scope |
| 195 | 197 |
| 196 // Make sure the (new) file is the right size. | 198 // Make sure the (new) file is the right size. |
| 197 if (size && (posix_flags & (O_RDWR | O_CREAT))) { | 199 if (size && (posix_flags & (O_RDWR | O_CREAT))) { |
| 198 // Get current size. | 200 // Get current size. |
| 199 struct stat stat; | 201 struct stat stat; |
| 200 if (fstat(fileno(fp), &stat) != 0) | 202 if (fstat(fileno(fp), &stat) != 0) |
| 201 return false; | 203 return false; |
| 202 const size_t current_size = stat.st_size; | 204 const size_t current_size = stat.st_size; |
| 203 if (current_size != size) { | 205 if (current_size != size) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 | 302 |
| 301 void SharedMemory::Unlock() { | 303 void SharedMemory::Unlock() { |
| 302 LockOrUnlockCommon(F_ULOCK); | 304 LockOrUnlockCommon(F_ULOCK); |
| 303 } | 305 } |
| 304 | 306 |
| 305 SharedMemoryHandle SharedMemory::handle() const { | 307 SharedMemoryHandle SharedMemory::handle() const { |
| 306 return FileDescriptor(mapped_file_, false); | 308 return FileDescriptor(mapped_file_, false); |
| 307 } | 309 } |
| 308 | 310 |
| 309 } // namespace base | 311 } // namespace base |
| OLD | NEW |