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

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

Issue 191673003: Implement ScopedFD in terms of ScopedGeneric. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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 | Annotate | Revision Log
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 <sys/mman.h> 9 #include <sys/mman.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 12 matching lines...) Expand all
23 23
24 #if defined(OS_MACOSX) 24 #if defined(OS_MACOSX)
25 #include "base/mac/foundation_util.h" 25 #include "base/mac/foundation_util.h"
26 #endif // OS_MACOSX 26 #endif // OS_MACOSX
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 using file_util::ScopedFD;
34 using file_util::ScopedFILE; 33 using file_util::ScopedFILE;
35 34
36 namespace base { 35 namespace base {
37 36
38 namespace { 37 namespace {
39 38
40 LazyInstance<Lock>::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER; 39 LazyInstance<Lock>::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER;
41 40
42 } 41 }
43 42
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) 124 if (options.size > static_cast<size_t>(std::numeric_limits<int>::max()))
126 return false; 125 return false;
127 126
128 // This function theoretically can block on the disk, but realistically 127 // This function theoretically can block on the disk, but realistically
129 // the temporary files we create will just go into the buffer cache 128 // the temporary files we create will just go into the buffer cache
130 // and be deleted before they ever make it out to disk. 129 // and be deleted before they ever make it out to disk.
131 base::ThreadRestrictions::ScopedAllowIO allow_io; 130 base::ThreadRestrictions::ScopedAllowIO allow_io;
132 131
133 ScopedFILE fp; 132 ScopedFILE fp;
134 bool fix_size = true; 133 bool fix_size = true;
135 int readonly_fd_storage = -1; 134 ScopedFD readonly_fd;
136 ScopedFD readonly_fd(&readonly_fd_storage);
137 135
138 FilePath path; 136 FilePath path;
139 if (options.name_deprecated == NULL || options.name_deprecated->empty()) { 137 if (options.name_deprecated == NULL || options.name_deprecated->empty()) {
140 // It doesn't make sense to have a open-existing private piece of shmem 138 // It doesn't make sense to have a open-existing private piece of shmem
141 DCHECK(!options.open_existing_deprecated); 139 DCHECK(!options.open_existing_deprecated);
142 // Q: Why not use the shm_open() etc. APIs? 140 // Q: Why not use the shm_open() etc. APIs?
143 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU 141 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU
144 fp.reset(base::CreateAndOpenTemporaryShmemFile(&path, options.executable)); 142 fp.reset(base::CreateAndOpenTemporaryShmemFile(&path, options.executable));
145 143
146 if (fp) { 144 if (fp) {
147 // Also open as readonly so that we can ShareReadOnlyToProcess. 145 // Also open as readonly so that we can ShareReadOnlyToProcess.
148 *readonly_fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)); 146 readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
149 if (*readonly_fd < 0) { 147 if (!readonly_fd.is_valid()) {
150 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 148 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
151 fp.reset(); 149 fp.reset();
152 } 150 }
153 // Deleting the file prevents anyone else from mapping it in (making it 151 // Deleting the file prevents anyone else from mapping it in (making it
154 // private), and prevents the need for cleanup (once the last fd is 152 // private), and prevents the need for cleanup (once the last fd is
155 // closed, it is truly freed). 153 // closed, it is truly freed).
156 if (unlink(path.value().c_str())) 154 if (unlink(path.value().c_str()))
157 PLOG(WARNING) << "unlink"; 155 PLOG(WARNING) << "unlink";
158 } 156 }
159 } else { 157 } else {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 "Invalid owner when opening existing shared memory file."; 189 "Invalid owner when opening existing shared memory file.";
192 close(fd); 190 close(fd);
193 return false; 191 return false;
194 } 192 }
195 193
196 // An existing file was opened, so its size should not be fixed. 194 // An existing file was opened, so its size should not be fixed.
197 fix_size = false; 195 fix_size = false;
198 } 196 }
199 197
200 // Also open as readonly so that we can ShareReadOnlyToProcess. 198 // Also open as readonly so that we can ShareReadOnlyToProcess.
201 *readonly_fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)); 199 readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
202 if (*readonly_fd < 0) { 200 if (!readonly_fd.is_valid()) {
203 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 201 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
204 close(fd); 202 close(fd);
205 fd = -1; 203 fd = -1;
206 } 204 }
207 if (fd >= 0) { 205 if (fd >= 0) {
208 // "a+" is always appropriate: if it's a new file, a+ is similar to w+. 206 // "a+" is always appropriate: if it's a new file, a+ is similar to w+.
209 fp.reset(fdopen(fd, "a+")); 207 fp.reset(fdopen(fd, "a+"));
210 } 208 }
211 } 209 }
212 if (fp && fix_size) { 210 if (fp && fix_size) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 256
259 bool SharedMemory::Open(const std::string& name, bool read_only) { 257 bool SharedMemory::Open(const std::string& name, bool read_only) {
260 FilePath path; 258 FilePath path;
261 if (!FilePathForMemoryName(name, &path)) 259 if (!FilePathForMemoryName(name, &path))
262 return false; 260 return false;
263 261
264 read_only_ = read_only; 262 read_only_ = read_only;
265 263
266 const char *mode = read_only ? "r" : "r+"; 264 const char *mode = read_only ? "r" : "r+";
267 ScopedFILE fp(base::OpenFile(path, mode)); 265 ScopedFILE fp(base::OpenFile(path, mode));
268 int readonly_fd_storage = -1; 266 ScopedFD readonly_fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
269 ScopedFD readonly_fd(&readonly_fd_storage); 267 if (!readonly_fd.is_valid()) {
270 *readonly_fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY));
271 if (*readonly_fd < 0) {
272 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed"; 268 DPLOG(ERROR) << "open(\"" << path.value() << "\", O_RDONLY) failed";
273 } 269 }
274 return PrepareMapFile(fp.Pass(), readonly_fd.Pass()); 270 return PrepareMapFile(fp.Pass(), readonly_fd.Pass());
275 } 271 }
276 272
277 #endif // !defined(OS_ANDROID) 273 #endif // !defined(OS_ANDROID)
278 274
279 bool SharedMemory::MapAt(off_t offset, size_t bytes) { 275 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
280 if (mapped_file_ == -1) 276 if (mapped_file_ == -1)
281 return false; 277 return false;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 342
347 void SharedMemory::UnlockDeprecated() { 343 void SharedMemory::UnlockDeprecated() {
348 LockOrUnlockCommon(F_ULOCK); 344 LockOrUnlockCommon(F_ULOCK);
349 g_thread_lock_.Get().Release(); 345 g_thread_lock_.Get().Release();
350 } 346 }
351 347
352 #if !defined(OS_ANDROID) 348 #if !defined(OS_ANDROID)
353 bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) { 349 bool SharedMemory::PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd) {
354 DCHECK_EQ(-1, mapped_file_); 350 DCHECK_EQ(-1, mapped_file_);
355 DCHECK_EQ(-1, readonly_mapped_file_); 351 DCHECK_EQ(-1, readonly_mapped_file_);
356 if (fp == NULL || *readonly_fd < 0) return false; 352 if (fp == NULL || !readonly_fd.is_valid()) return false;
357 353
358 // This function theoretically can block on the disk, but realistically 354 // This function theoretically can block on the disk, but realistically
359 // the temporary files we create will just go into the buffer cache 355 // the temporary files we create will just go into the buffer cache
360 // and be deleted before they ever make it out to disk. 356 // and be deleted before they ever make it out to disk.
361 base::ThreadRestrictions::ScopedAllowIO allow_io; 357 base::ThreadRestrictions::ScopedAllowIO allow_io;
362 358
363 struct stat st = {}; 359 struct stat st = {};
364 struct stat readonly_st = {}; 360 struct stat readonly_st = {};
365 if (fstat(fileno(fp.get()), &st)) 361 if (fstat(fileno(fp.get()), &st))
366 NOTREACHED(); 362 NOTREACHED();
367 if (fstat(*readonly_fd, &readonly_st)) 363 if (fstat(readonly_fd.get(), &readonly_st))
368 NOTREACHED(); 364 NOTREACHED();
369 if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { 365 if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) {
370 LOG(ERROR) << "writable and read-only inodes don't match; bailing"; 366 LOG(ERROR) << "writable and read-only inodes don't match; bailing";
371 return false; 367 return false;
372 } 368 }
373 369
374 mapped_file_ = dup(fileno(fp.get())); 370 mapped_file_ = dup(fileno(fp.get()));
375 if (mapped_file_ == -1) { 371 if (mapped_file_ == -1) {
376 if (errno == EMFILE) { 372 if (errno == EMFILE) {
377 LOG(WARNING) << "Shared memory creation failed; out of file descriptors"; 373 LOG(WARNING) << "Shared memory creation failed; out of file descriptors";
378 return false; 374 return false;
379 } else { 375 } else {
380 NOTREACHED() << "Call to dup failed, errno=" << errno; 376 NOTREACHED() << "Call to dup failed, errno=" << errno;
381 } 377 }
382 } 378 }
383 inode_ = st.st_ino; 379 inode_ = st.st_ino;
384 readonly_mapped_file_ = *readonly_fd.release(); 380 readonly_mapped_file_ = readonly_fd.release();
385 381
386 return true; 382 return true;
387 } 383 }
388 #endif 384 #endif
389 385
390 // For the given shmem named |mem_name|, return a filename to mmap() 386 // For the given shmem named |mem_name|, return a filename to mmap()
391 // (and possibly create). Modifies |filename|. Return false on 387 // (and possibly create). Modifies |filename|. Return false on
392 // error, or true of we are happy. 388 // error, or true of we are happy.
393 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, 389 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
394 FilePath* path) { 390 FilePath* path) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 new_handle->fd = new_fd; 455 new_handle->fd = new_fd;
460 new_handle->auto_close = true; 456 new_handle->auto_close = true;
461 457
462 if (close_self) 458 if (close_self)
463 Close(); 459 Close();
464 460
465 return true; 461 return true;
466 } 462 }
467 463
468 } // namespace base 464 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698