Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(592)

Side by Side Diff: base/memory/shared_memory_posix.cc

Issue 2845113005: Replace base::SharedMemory read-only methods with GetReadOnlyHandle. (Closed)
Patch Set: Comments from thakis. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/memory/shared_memory_nacl.cc ('k') | base/memory/shared_memory_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/memory/shared_memory.h" 5 #include "base/memory/shared_memory.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
(...skipping 15 matching lines...) Expand all
26 #include "build/build_config.h" 26 #include "build/build_config.h"
27 27
28 #if defined(OS_ANDROID) 28 #if defined(OS_ANDROID)
29 #include "base/os_compat_android.h" 29 #include "base/os_compat_android.h"
30 #include "third_party/ashmem/ashmem.h" 30 #include "third_party/ashmem/ashmem.h"
31 #endif 31 #endif
32 32
33 namespace base { 33 namespace base {
34 34
35 SharedMemory::SharedMemory() 35 SharedMemory::SharedMemory()
36 : readonly_mapped_file_(-1), 36 : mapped_size_(0), memory_(NULL), read_only_(false), requested_size_(0) {}
37 mapped_size_(0),
38 memory_(NULL),
39 read_only_(false),
40 requested_size_(0) {}
41 37
42 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) 38 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
43 : shm_(handle), 39 : shm_(handle),
44 readonly_mapped_file_(-1), 40
45 mapped_size_(0), 41 mapped_size_(0),
46 memory_(NULL), 42 memory_(NULL),
47 read_only_(read_only), 43 read_only_(read_only),
48 requested_size_(0) {} 44 requested_size_(0) {}
49 45
50 SharedMemory::~SharedMemory() { 46 SharedMemory::~SharedMemory() {
51 Unmap(); 47 Unmap();
52 Close(); 48 Close();
53 } 49 }
54 50
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 "Invalid owner when opening existing shared memory file."; 162 "Invalid owner when opening existing shared memory file.";
167 close(fd); 163 close(fd);
168 return false; 164 return false;
169 } 165 }
170 166
171 // An existing file was opened, so its size should not be fixed. 167 // An existing file was opened, so its size should not be fixed.
172 fix_size = false; 168 fix_size = false;
173 } 169 }
174 170
175 if (options.share_read_only) { 171 if (options.share_read_only) {
176 // Also open as readonly so that we can ShareReadOnlyToProcess. 172 // Also open as readonly so that we can GetReadOnlyHandle.
177 readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); 173 readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
178 if (!readonly_fd.is_valid()) { 174 if (!readonly_fd.is_valid()) {
179 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 175 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
180 close(fd); 176 close(fd);
181 fd = -1; 177 fd = -1;
182 return false; 178 return false;
183 } 179 }
184 } 180 }
185 if (fd >= 0) { 181 if (fd >= 0) {
186 // "a+" is always appropriate: if it's a new file, a+ is similar to w+. 182 // "a+" is always appropriate: if it's a new file, a+ is similar to w+.
(...skipping 19 matching lines...) Expand all
206 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); 202 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value();
207 if (dir.value() == "/dev/shm") { 203 if (dir.value() == "/dev/shm") {
208 LOG(FATAL) << "This is frequently caused by incorrect permissions on " 204 LOG(FATAL) << "This is frequently caused by incorrect permissions on "
209 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; 205 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix.";
210 } 206 }
211 } 207 }
212 return false; 208 return false;
213 } 209 }
214 210
215 int mapped_file = -1; 211 int mapped_file = -1;
212 int readonly_mapped_file = -1;
216 bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd), 213 bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd),
217 &mapped_file, &readonly_mapped_file_); 214 &mapped_file, &readonly_mapped_file);
218 shm_ = SharedMemoryHandle::ImportHandle(mapped_file); 215 shm_ = SharedMemoryHandle::ImportHandle(mapped_file);
216 readonly_shm_ = SharedMemoryHandle::ImportHandle(readonly_mapped_file);
219 return result; 217 return result;
220 } 218 }
221 219
222 // Our current implementation of shmem is with mmap()ing of files. 220 // Our current implementation of shmem is with mmap()ing of files.
223 // These files need to be deleted explicitly. 221 // These files need to be deleted explicitly.
224 // In practice this call is only needed for unit tests. 222 // In practice this call is only needed for unit tests.
225 bool SharedMemory::Delete(const std::string& name) { 223 bool SharedMemory::Delete(const std::string& name) {
226 FilePath path; 224 FilePath path;
227 if (!FilePathForMemoryName(name, &path)) 225 if (!FilePathForMemoryName(name, &path))
228 return false; 226 return false;
(...skipping 13 matching lines...) Expand all
242 read_only_ = read_only; 240 read_only_ = read_only;
243 241
244 const char *mode = read_only ? "r" : "r+"; 242 const char *mode = read_only ? "r" : "r+";
245 ScopedFILE fp(base::OpenFile(path, mode)); 243 ScopedFILE fp(base::OpenFile(path, mode));
246 ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); 244 ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
247 if (!readonly_fd.is_valid()) { 245 if (!readonly_fd.is_valid()) {
248 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 246 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
249 return false; 247 return false;
250 } 248 }
251 int mapped_file = -1; 249 int mapped_file = -1;
250 int readonly_mapped_file = -1;
252 bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd), 251 bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd),
253 &mapped_file, &readonly_mapped_file_); 252 &mapped_file, &readonly_mapped_file);
254 shm_ = SharedMemoryHandle::ImportHandle(mapped_file); 253 shm_ = SharedMemoryHandle::ImportHandle(mapped_file);
254 readonly_shm_ = SharedMemoryHandle::ImportHandle(readonly_mapped_file);
255 return result; 255 return result;
256 } 256 }
257 #endif // !defined(OS_ANDROID) 257 #endif // !defined(OS_ANDROID)
258 258
259 bool SharedMemory::MapAt(off_t offset, size_t bytes) { 259 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
260 if (!shm_.IsValid()) 260 if (!shm_.IsValid())
261 return false; 261 return false;
262 262
263 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) 263 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
264 return false; 264 return false;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 memory_ = nullptr; 317 memory_ = nullptr;
318 mapped_size_ = 0; 318 mapped_size_ = 0;
319 return handle_copy; 319 return handle_copy;
320 } 320 }
321 321
322 void SharedMemory::Close() { 322 void SharedMemory::Close() {
323 if (shm_.IsValid()) { 323 if (shm_.IsValid()) {
324 shm_.Close(); 324 shm_.Close();
325 shm_ = SharedMemoryHandle(); 325 shm_ = SharedMemoryHandle();
326 } 326 }
327 if (readonly_mapped_file_ > 0) { 327 if (readonly_shm_.IsValid()) {
328 if (IGNORE_EINTR(close(readonly_mapped_file_)) < 0) 328 readonly_shm_.Close();
329 PLOG(ERROR) << "close"; 329 readonly_shm_ = SharedMemoryHandle();
330 readonly_mapped_file_ = -1;
331 } 330 }
332 } 331 }
333 332
334 #if !defined(OS_ANDROID) 333 #if !defined(OS_ANDROID)
335 // For the given shmem named |mem_name|, return a filename to mmap() 334 // For the given shmem named |mem_name|, return a filename to mmap()
336 // (and possibly create). Modifies |filename|. Return false on 335 // (and possibly create). Modifies |filename|. Return false on
337 // error, or true of we are happy. 336 // error, or true of we are happy.
338 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, 337 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
339 FilePath* path) { 338 FilePath* path) {
340 // mem_name will be used for a filename; make sure it doesn't 339 // mem_name will be used for a filename; make sure it doesn't
341 // contain anything which will confuse us. 340 // contain anything which will confuse us.
342 DCHECK_EQ(std::string::npos, mem_name.find('/')); 341 DCHECK_EQ(std::string::npos, mem_name.find('/'));
343 DCHECK_EQ(std::string::npos, mem_name.find('\0')); 342 DCHECK_EQ(std::string::npos, mem_name.find('\0'));
344 343
345 FilePath temp_dir; 344 FilePath temp_dir;
346 if (!GetShmemTempDir(false, &temp_dir)) 345 if (!GetShmemTempDir(false, &temp_dir))
347 return false; 346 return false;
348 347
349 #if defined(GOOGLE_CHROME_BUILD) 348 #if defined(GOOGLE_CHROME_BUILD)
350 std::string name_base = std::string("com.google.Chrome"); 349 std::string name_base = std::string("com.google.Chrome");
351 #else 350 #else
352 std::string name_base = std::string("org.chromium.Chromium"); 351 std::string name_base = std::string("org.chromium.Chromium");
353 #endif 352 #endif
354 *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name); 353 *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name);
355 return true; 354 return true;
356 } 355 }
357 #endif // !defined(OS_ANDROID) 356 #endif // !defined(OS_ANDROID)
358 357
358 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() {
359 CHECK(readonly_shm_.IsValid());
360 return readonly_shm_.Duplicate();
361 }
362
359 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, 363 bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
360 SharedMemoryHandle* new_handle, 364 SharedMemoryHandle* new_handle,
361 bool close_self, 365 bool close_self) {
362 ShareMode share_mode) { 366 *new_handle = shm_.Duplicate();
363 int handle_to_dup = -1;
364 switch(share_mode) {
365 case SHARE_CURRENT_MODE:
366 handle_to_dup = shm_.GetHandle();
367 break;
368 case SHARE_READONLY:
369 // We could imagine re-opening the file from /dev/fd, but that can't make
370 // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10
371 CHECK_GE(readonly_mapped_file_, 0);
372 handle_to_dup = readonly_mapped_file_;
373 break;
374 }
375
376 const int new_fd = HANDLE_EINTR(dup(handle_to_dup));
377 if (new_fd < 0) {
378 if (close_self) {
379 Unmap();
380 Close();
381 }
382 DPLOG(ERROR) << "dup() failed.";
383 return false;
384 }
385
386 new_handle->SetHandle(new_fd);
387 new_handle->SetOwnershipPassesToIPC(true);
388
389 if (close_self) { 367 if (close_self) {
390 Unmap(); 368 Unmap();
391 Close(); 369 Close();
392 } 370 }
393 371 return new_handle->IsValid();
394 return true;
395 } 372 }
396 373
397 bool SharedMemory::GetUniqueId(SharedMemory::UniqueId* id) const { 374 bool SharedMemory::GetUniqueId(SharedMemory::UniqueId* id) const {
398 // This function is called just after mmap. fstat is a system call that might 375 // This function is called just after mmap. fstat is a system call that might
399 // cause I/O. It's safe to call fstat here because mmap for shared memory is 376 // cause I/O. It's safe to call fstat here because mmap for shared memory is
400 // called in two cases: 377 // called in two cases:
401 // 1) To handle file-mapped memory 378 // 1) To handle file-mapped memory
402 // 2) To handle annonymous shared memory 379 // 2) To handle annonymous shared memory
403 // In 1), I/O is already permitted. In 2), the backend is on page cache and 380 // In 1), I/O is already permitted. In 2), the backend is on page cache and
404 // fstat doesn't cause I/O access to the disk. See the discussion at 381 // fstat doesn't cause I/O access to the disk. See the discussion at
405 // crbug.com/604726#c41. 382 // crbug.com/604726#c41.
406 base::ThreadRestrictions::ScopedAllowIO allow_io; 383 base::ThreadRestrictions::ScopedAllowIO allow_io;
407 struct stat file_stat; 384 struct stat file_stat;
408 if (HANDLE_EINTR( 385 if (HANDLE_EINTR(
409 ::fstat(static_cast<int>(handle().GetHandle()), &file_stat)) != 0) 386 ::fstat(static_cast<int>(handle().GetHandle()), &file_stat)) != 0)
410 return false; 387 return false;
411 id->first = file_stat.st_dev; 388 id->first = file_stat.st_dev;
412 id->second = file_stat.st_ino; 389 id->second = file_stat.st_ino;
413 return true; 390 return true;
414 } 391 }
415 392
416 } // namespace base 393 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/shared_memory_nacl.cc ('k') | base/memory/shared_memory_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698