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 |