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

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

Issue 1163943004: Make SharedMemoryHandle a class on Mac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shared_memory_make_class3_base
Patch Set: Remove more unused headers that magically appeared from rebase. Created 5 years, 6 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_handle_mac.cc ('k') | base/memory/shared_memory_nacl.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 <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/mman.h> 8 #include <sys/mman.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/files/scoped_file.h" 13 #include "base/files/scoped_file.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
16 #include "base/posix/safe_strerror.h" 16 #include "base/posix/safe_strerror.h"
17 #include "base/process/process_metrics.h" 17 #include "base/process/process_metrics.h"
18 #include "base/profiler/scoped_tracker.h" 18 #include "base/profiler/scoped_tracker.h"
19 #include "base/scoped_generic.h" 19 #include "base/scoped_generic.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 21
22 #if defined(OS_MACOSX) 22 #if defined(OS_MACOSX)
23 #include "base/mac/foundation_util.h" 23 #include "base/mac/foundation_util.h"
24 #endif // OS_MACOSX 24 #endif // OS_MACOSX
25 25
26 #if defined(OS_ANDROID)
27 #include "base/os_compat_android.h"
28 #include "third_party/ashmem/ashmem.h"
29 #endif
30
31 namespace base { 26 namespace base {
32 27
33 namespace { 28 namespace {
34 29
35 struct ScopedPathUnlinkerTraits { 30 struct ScopedPathUnlinkerTraits {
36 static FilePath* InvalidValue() { return nullptr; } 31 static FilePath* InvalidValue() { return nullptr; }
37 32
38 static void Free(FilePath* path) { 33 static void Free(FilePath* path) {
39 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 34 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437
40 // is fixed. 35 // is fixed.
41 tracked_objects::ScopedTracker tracking_profile( 36 tracked_objects::ScopedTracker tracking_profile(
42 FROM_HERE_WITH_EXPLICIT_FUNCTION( 37 FROM_HERE_WITH_EXPLICIT_FUNCTION(
43 "466437 SharedMemory::Create::Unlink")); 38 "466437 SharedMemory::Create::Unlink"));
44 if (unlink(path->value().c_str())) 39 if (unlink(path->value().c_str()))
45 PLOG(WARNING) << "unlink"; 40 PLOG(WARNING) << "unlink";
46 } 41 }
47 }; 42 };
48 43
49 // Unlinks the FilePath when the object is destroyed. 44 // Unlinks the FilePath when the object is destroyed.
50 typedef ScopedGeneric<FilePath*, ScopedPathUnlinkerTraits> ScopedPathUnlinker; 45 typedef ScopedGeneric<FilePath*, ScopedPathUnlinkerTraits> ScopedPathUnlinker;
51 46
52 #if !defined(OS_ANDROID)
53 // Makes a temporary file, fdopens it, and then unlinks it. |fp| is populated 47 // Makes a temporary file, fdopens it, and then unlinks it. |fp| is populated
54 // with the fdopened FILE. |readonly_fd| is populated with the opened fd if 48 // with the fdopened FILE. |readonly_fd| is populated with the opened fd if
55 // options.share_read_only is true. |path| is populated with the location of 49 // options.share_read_only is true. |path| is populated with the location of
56 // the file before it was unlinked. 50 // the file before it was unlinked.
57 // Returns false if there's an unhandled failure. 51 // Returns false if there's an unhandled failure.
58 bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, 52 bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options,
59 ScopedFILE* fp, 53 ScopedFILE* fp,
60 ScopedFD* readonly_fd, 54 ScopedFD* readonly_fd,
61 FilePath* path) { 55 FilePath* path) {
62 // It doesn't make sense to have a open-existing private piece of shmem 56 // It doesn't make sense to have a open-existing private piece of shmem
(...skipping 28 matching lines...) Expand all
91 readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY))); 85 readonly_fd->reset(HANDLE_EINTR(open(path->value().c_str(), O_RDONLY)));
92 if (!readonly_fd->is_valid()) { 86 if (!readonly_fd->is_valid()) {
93 DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; 87 DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed";
94 fp->reset(); 88 fp->reset();
95 return false; 89 return false;
96 } 90 }
97 } 91 }
98 } 92 }
99 return true; 93 return true;
100 } 94 }
101 #endif // !defined(OS_ANDROID)
102 } 95 }
103 96
104 SharedMemory::SharedMemory() 97 SharedMemory::SharedMemory()
105 : mapped_file_(-1), 98 : mapped_file_(-1),
106 readonly_mapped_file_(-1), 99 readonly_mapped_file_(-1),
107 mapped_size_(0), 100 mapped_size_(0),
108 memory_(NULL), 101 memory_(NULL),
109 read_only_(false), 102 read_only_(false),
110 requested_size_(0) { 103 requested_size_(0) {
111 } 104 }
112 105
113 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) 106 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
114 : mapped_file_(handle.fd), 107 : mapped_file_(GetFdFromSharedMemoryHandle(handle)),
115 readonly_mapped_file_(-1), 108 readonly_mapped_file_(-1),
116 mapped_size_(0), 109 mapped_size_(0),
117 memory_(NULL), 110 memory_(NULL),
118 read_only_(read_only), 111 read_only_(read_only),
119 requested_size_(0) { 112 requested_size_(0) {
120 } 113 }
121 114
122 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, 115 SharedMemory::SharedMemory(const SharedMemoryHandle& handle,
116 bool read_only,
123 ProcessHandle process) 117 ProcessHandle process)
124 : mapped_file_(handle.fd), 118 : mapped_file_(GetFdFromSharedMemoryHandle(handle)),
125 readonly_mapped_file_(-1), 119 readonly_mapped_file_(-1),
126 mapped_size_(0), 120 mapped_size_(0),
127 memory_(NULL), 121 memory_(NULL),
128 read_only_(read_only), 122 read_only_(read_only),
129 requested_size_(0) { 123 requested_size_(0) {
130 // We don't handle this case yet (note the ignored parameter); let's die if 124 // We don't handle this case yet (note the ignored parameter); let's die if
131 // someone comes calling. 125 // someone comes calling.
132 NOTREACHED(); 126 NOTREACHED();
133 } 127 }
134 128
135 SharedMemory::~SharedMemory() { 129 SharedMemory::~SharedMemory() {
136 Unmap(); 130 Unmap();
137 Close(); 131 Close();
138 } 132 }
139 133
140 // static 134 // static
141 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { 135 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
142 return handle.fd >= 0; 136 return handle.IsValid();
143 } 137 }
144 138
145 // static 139 // static
146 SharedMemoryHandle SharedMemory::NULLHandle() { 140 SharedMemoryHandle SharedMemory::NULLHandle() {
147 return SharedMemoryHandle(); 141 return SharedMemoryHandle();
148 } 142 }
149 143
150 // static 144 // static
151 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { 145 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
152 DCHECK_GE(handle.fd, 0); 146 DCHECK_GE(GetFdFromSharedMemoryHandle(handle), 0);
153 if (close(handle.fd) < 0) 147 if (close(GetFdFromSharedMemoryHandle(handle)) < 0)
154 DPLOG(ERROR) << "close"; 148 DPLOG(ERROR) << "close";
155 } 149 }
156 150
157 // static 151 // static
158 size_t SharedMemory::GetHandleLimit() { 152 size_t SharedMemory::GetHandleLimit() {
159 return base::GetMaxFds(); 153 return base::GetMaxFds();
160 } 154 }
161 155
162 // static 156 // static
163 SharedMemoryHandle SharedMemory::DuplicateHandle( 157 SharedMemoryHandle SharedMemory::DuplicateHandle(
164 const SharedMemoryHandle& handle) { 158 const SharedMemoryHandle& handle) {
165 int duped_handle = HANDLE_EINTR(dup(handle.fd)); 159 return handle.Duplicate();
166 if (duped_handle < 0)
167 return base::SharedMemory::NULLHandle();
168 return base::FileDescriptor(duped_handle, true);
169 } 160 }
170 161
171 // static 162 // static
172 int SharedMemory::GetFdFromSharedMemoryHandle( 163 int SharedMemory::GetFdFromSharedMemoryHandle(
173 const SharedMemoryHandle& handle) { 164 const SharedMemoryHandle& handle) {
174 return handle.fd; 165 return handle.GetFileDescriptor().fd;
175 } 166 }
176 167
177 bool SharedMemory::CreateAndMapAnonymous(size_t size) { 168 bool SharedMemory::CreateAndMapAnonymous(size_t size) {
178 return CreateAnonymous(size) && Map(size); 169 return CreateAnonymous(size) && Map(size);
179 } 170 }
180 171
181 #if !defined(OS_ANDROID)
182 // static 172 // static
183 int SharedMemory::GetSizeFromSharedMemoryHandle( 173 int SharedMemory::GetSizeFromSharedMemoryHandle(
184 const SharedMemoryHandle& handle) { 174 const SharedMemoryHandle& handle) {
185 struct stat st; 175 struct stat st;
186 if (fstat(handle.fd, &st) != 0) 176 if (fstat(GetFdFromSharedMemoryHandle(handle), &st) != 0)
187 return -1; 177 return -1;
188 return st.st_size; 178 return st.st_size;
189 } 179 }
190 180
191 // Chromium mostly only uses the unique/private shmem as specified by 181 // Chromium mostly only uses the unique/private shmem as specified by
192 // "name == L"". The exception is in the StatsTable. 182 // "name == L"". The exception is in the StatsTable.
193 // TODO(jrg): there is no way to "clean up" all unused named shmem if 183 // TODO(jrg): there is no way to "clean up" all unused named shmem if
194 // we restart from a crash. (That isn't a new problem, but it is a problem.) 184 // we restart from a crash. (That isn't a new problem, but it is a problem.)
195 // In case we want to delete it later, it may be useful to save the value 185 // In case we want to delete it later, it may be useful to save the value
196 // of mem_filename after FilePathForMemoryName(). 186 // of mem_filename after FilePathForMemoryName().
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 if (fstat(fileno(fp.get()), &stat) != 0) 273 if (fstat(fileno(fp.get()), &stat) != 0)
284 return false; 274 return false;
285 const size_t current_size = stat.st_size; 275 const size_t current_size = stat.st_size;
286 if (current_size != options.size) { 276 if (current_size != options.size) {
287 if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) 277 if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0)
288 return false; 278 return false;
289 } 279 }
290 requested_size_ = options.size; 280 requested_size_ = options.size;
291 } 281 }
292 if (fp == NULL) { 282 if (fp == NULL) {
293 #if !defined(OS_MACOSX)
294 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; 283 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed";
295 FilePath dir = path.DirName();
296 if (access(dir.value().c_str(), W_OK | X_OK) < 0) {
297 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value();
298 if (dir.value() == "/dev/shm") {
299 LOG(FATAL) << "This is frequently caused by incorrect permissions on "
300 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix.";
301 }
302 }
303 #else
304 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed";
305 #endif
306 return false; 284 return false;
307 } 285 }
308 286
309 return PrepareMapFile(fp.Pass(), readonly_fd.Pass()); 287 return PrepareMapFile(fp.Pass(), readonly_fd.Pass());
310 } 288 }
311 289
312 // Our current implementation of shmem is with mmap()ing of files. 290 // Our current implementation of shmem is with mmap()ing of files.
313 // These files need to be deleted explicitly. 291 // These files need to be deleted explicitly.
314 // In practice this call is only needed for unit tests. 292 // In practice this call is only needed for unit tests.
315 bool SharedMemory::Delete(const std::string& name) { 293 bool SharedMemory::Delete(const std::string& name) {
(...skipping 17 matching lines...) Expand all
333 311
334 const char *mode = read_only ? "r" : "r+"; 312 const char *mode = read_only ? "r" : "r+";
335 ScopedFILE fp(base::OpenFile(path, mode)); 313 ScopedFILE fp(base::OpenFile(path, mode));
336 ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); 314 ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
337 if (!readonly_fd.is_valid()) { 315 if (!readonly_fd.is_valid()) {
338 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 316 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
339 return false; 317 return false;
340 } 318 }
341 return PrepareMapFile(fp.Pass(), readonly_fd.Pass()); 319 return PrepareMapFile(fp.Pass(), readonly_fd.Pass());
342 } 320 }
343 #endif // !defined(OS_ANDROID)
344 321
345 bool SharedMemory::MapAt(off_t offset, size_t bytes) { 322 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
346 if (mapped_file_ == -1) 323 if (mapped_file_ == -1)
347 return false; 324 return false;
348 325
349 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) 326 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
350 return false; 327 return false;
351 328
352 if (memory_) 329 if (memory_)
353 return false; 330 return false;
354 331
355 #if defined(OS_ANDROID)
356 // On Android, Map can be called with a size and offset of zero to use the
357 // ashmem-determined size.
358 if (bytes == 0) {
359 DCHECK_EQ(0, offset);
360 int ashmem_bytes = ashmem_get_size_region(mapped_file_);
361 if (ashmem_bytes < 0)
362 return false;
363 bytes = ashmem_bytes;
364 }
365 #endif
366
367 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), 332 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
368 MAP_SHARED, mapped_file_, offset); 333 MAP_SHARED, mapped_file_, offset);
369 334
370 bool mmap_succeeded = memory_ != (void*)-1 && memory_ != NULL; 335 bool mmap_succeeded = memory_ != (void*)-1 && memory_ != NULL;
371 if (mmap_succeeded) { 336 if (mmap_succeeded) {
372 mapped_size_ = bytes; 337 mapped_size_ = bytes;
373 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & 338 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
374 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 339 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
375 } else { 340 } else {
376 memory_ = NULL; 341 memory_ = NULL;
377 } 342 }
378 343
379 return mmap_succeeded; 344 return mmap_succeeded;
380 } 345 }
381 346
382 bool SharedMemory::Unmap() { 347 bool SharedMemory::Unmap() {
383 if (memory_ == NULL) 348 if (memory_ == NULL)
384 return false; 349 return false;
385 350
386 munmap(memory_, mapped_size_); 351 munmap(memory_, mapped_size_);
387 memory_ = NULL; 352 memory_ = NULL;
388 mapped_size_ = 0; 353 mapped_size_ = 0;
389 return true; 354 return true;
390 } 355 }
391 356
392 SharedMemoryHandle SharedMemory::handle() const { 357 SharedMemoryHandle SharedMemory::handle() const {
393 return FileDescriptor(mapped_file_, false); 358 return SharedMemoryHandle(mapped_file_, false);
394 } 359 }
395 360
396 void SharedMemory::Close() { 361 void SharedMemory::Close() {
397 if (mapped_file_ > 0) { 362 if (mapped_file_ > 0) {
398 if (close(mapped_file_) < 0) 363 if (close(mapped_file_) < 0)
399 PLOG(ERROR) << "close"; 364 PLOG(ERROR) << "close";
400 mapped_file_ = -1; 365 mapped_file_ = -1;
401 } 366 }
402 if (readonly_mapped_file_ > 0) { 367 if (readonly_mapped_file_ > 0) {
403 if (close(readonly_mapped_file_) < 0) 368 if (close(readonly_mapped_file_) < 0)
404 PLOG(ERROR) << "close"; 369 PLOG(ERROR) << "close";
405 readonly_mapped_file_ = -1; 370 readonly_mapped_file_ = -1;
406 } 371 }
407 } 372 }
408 373
409 #if !defined(OS_ANDROID)
410 bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { 374 bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) {
411 DCHECK_EQ(-1, mapped_file_); 375 DCHECK_EQ(-1, mapped_file_);
412 DCHECK_EQ(-1, readonly_mapped_file_); 376 DCHECK_EQ(-1, readonly_mapped_file_);
413 if (fp == NULL) 377 if (fp == NULL)
414 return false; 378 return false;
415 379
416 // This function theoretically can block on the disk, but realistically 380 // This function theoretically can block on the disk, but realistically
417 // the temporary files we create will just go into the buffer cache 381 // the temporary files we create will just go into the buffer cache
418 // and be deleted before they ever make it out to disk. 382 // and be deleted before they ever make it out to disk.
419 base::ThreadRestrictions::ScopedAllowIO allow_io; 383 base::ThreadRestrictions::ScopedAllowIO allow_io;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 FilePath* path) { 416 FilePath* path) {
453 // mem_name will be used for a filename; make sure it doesn't 417 // mem_name will be used for a filename; make sure it doesn't
454 // contain anything which will confuse us. 418 // contain anything which will confuse us.
455 DCHECK_EQ(std::string::npos, mem_name.find('/')); 419 DCHECK_EQ(std::string::npos, mem_name.find('/'));
456 DCHECK_EQ(std::string::npos, mem_name.find('\0')); 420 DCHECK_EQ(std::string::npos, mem_name.find('\0'));
457 421
458 FilePath temp_dir; 422 FilePath temp_dir;
459 if (!GetShmemTempDir(false, &temp_dir)) 423 if (!GetShmemTempDir(false, &temp_dir))
460 return false; 424 return false;
461 425
462 #if !defined(OS_MACOSX)
463 #if defined(GOOGLE_CHROME_BUILD)
464 std::string name_base = std::string("com.google.Chrome");
465 #else
466 std::string name_base = std::string("org.chromium.Chromium");
467 #endif
468 #else // OS_MACOSX
469 std::string name_base = std::string(base::mac::BaseBundleID()); 426 std::string name_base = std::string(base::mac::BaseBundleID());
470 #endif // OS_MACOSX
471 *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name); 427 *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name);
472 return true; 428 return true;
473 } 429 }
474 #endif // !defined(OS_ANDROID)
475 430
476 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, 431 bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
477 SharedMemoryHandle* new_handle, 432 SharedMemoryHandle* new_handle,
478 bool close_self, 433 bool close_self,
479 ShareMode share_mode) { 434 ShareMode share_mode) {
480 int handle_to_dup = -1; 435 int handle_to_dup = -1;
481 switch(share_mode) { 436 switch(share_mode) {
482 case SHARE_CURRENT_MODE: 437 case SHARE_CURRENT_MODE:
483 handle_to_dup = mapped_file_; 438 handle_to_dup = mapped_file_;
484 break; 439 break;
485 case SHARE_READONLY: 440 case SHARE_READONLY:
486 // We could imagine re-opening the file from /dev/fd, but that can't make 441 // We could imagine re-opening the file from /dev/fd, but that can't make
487 // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10 442 // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10
488 CHECK_GE(readonly_mapped_file_, 0); 443 CHECK_GE(readonly_mapped_file_, 0);
489 handle_to_dup = readonly_mapped_file_; 444 handle_to_dup = readonly_mapped_file_;
490 break; 445 break;
491 } 446 }
492 447
493 const int new_fd = HANDLE_EINTR(dup(handle_to_dup)); 448 const int new_fd = HANDLE_EINTR(dup(handle_to_dup));
494 if (new_fd < 0) { 449 if (new_fd < 0) {
495 DPLOG(ERROR) << "dup() failed."; 450 DPLOG(ERROR) << "dup() failed.";
496 return false; 451 return false;
497 } 452 }
498 453
499 new_handle->fd = new_fd; 454 new_handle->SetFileHandle(new_fd, true);
500 new_handle->auto_close = true;
501 455
502 if (close_self) { 456 if (close_self) {
503 Unmap(); 457 Unmap();
504 Close(); 458 Close();
505 } 459 }
506 460
507 return true; 461 return true;
508 } 462 }
509 463
510 } // namespace base 464 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/shared_memory_handle_mac.cc ('k') | base/memory/shared_memory_nacl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698