blob: 93e0b76fa2ccc5e625ca53d48b3061ecbd0ff73e [file] [log] [blame]
vandebo@chromium.org439b3d22012-02-25 15:28:56 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
avi@google.com3a208982008-08-13 06:06:40 +09004
brettw@chromium.org4329aa72013-03-30 02:46:23 +09005#include "base/memory/shared_memory.h"
avi@google.com3a208982008-08-13 06:06:40 +09006
avi@google.com8e4b6532008-12-12 04:51:24 +09007#include <errno.h>
tc@google.com7e1fb1d2008-08-13 07:40:21 +09008#include <fcntl.h>
avi@google.com3a208982008-08-13 06:06:40 +09009#include <sys/mman.h>
agl@chromium.org31de02e2009-02-20 11:00:04 +090010#include <sys/stat.h>
jln@chromium.orge77bef72013-07-03 08:31:55 +090011#include <sys/types.h>
agl@chromium.org31de02e2009-02-20 11:00:04 +090012#include <unistd.h>
avi@google.com3a208982008-08-13 06:06:40 +090013
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +090014#include "base/file_util.h"
vandebo@chromium.org439b3d22012-02-25 15:28:56 +090015#include "base/lazy_instance.h"
avi@google.com3a208982008-08-13 06:06:40 +090016#include "base/logging.h"
simonjam@chromium.org2afd4062013-05-10 08:15:40 +090017#include "base/process_util.h"
tschmelcher@chromium.org90a3f8a2009-10-14 03:27:40 +090018#include "base/safe_strerror_posix.h"
avi@chromium.org17f60622013-06-08 03:37:07 +090019#include "base/strings/utf_string_conversions.h"
vandebo@chromium.org439b3d22012-02-25 15:28:56 +090020#include "base/synchronization/lock.h"
simonjam@chromium.org2afd4062013-05-10 08:15:40 +090021#include "base/threading/platform_thread.h"
brettw@chromium.org5b5f5e02011-01-01 10:01:06 +090022#include "base/threading/thread_restrictions.h"
avi@google.com3a208982008-08-13 06:06:40 +090023
mark@chromium.org13aa8aa2011-04-22 13:15:13 +090024#if defined(OS_MACOSX)
25#include "base/mac/foundation_util.h"
26#endif // OS_MACOSX
27
michaelbai@google.com2251c622011-06-22 07:34:50 +090028#if defined(OS_ANDROID)
29#include "base/os_compat_android.h"
30#include "third_party/ashmem/ashmem.h"
31#endif
32
brettw@google.comc60d9892008-11-14 12:25:15 +090033namespace base {
34
avi@google.com3a208982008-08-13 06:06:40 +090035namespace {
michaelbai@google.com2251c622011-06-22 07:34:50 +090036
avi@google.com9e0cc152008-08-14 04:59:07 +090037// Paranoia. Semaphores and shared memory segments should live in different
38// namespaces, but who knows what's out there.
39const char kSemaphoreSuffix[] = "-sem";
michaelbai@google.com2251c622011-06-22 07:34:50 +090040
vandebo@chromium.org439b3d22012-02-25 15:28:56 +090041LazyInstance<Lock>::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER;
42
avi@google.com3a208982008-08-13 06:06:40 +090043}
44
45SharedMemory::SharedMemory()
46 : mapped_file_(-1),
agl@chromium.org31de02e2009-02-20 11:00:04 +090047 inode_(0),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090048 mapped_size_(0),
avi@google.com3a208982008-08-13 06:06:40 +090049 memory_(NULL),
50 read_only_(false),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090051 requested_size_(0) {
avi@google.com3a208982008-08-13 06:06:40 +090052}
53
54SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
agl@chromium.org42bbb992009-02-12 03:59:20 +090055 : mapped_file_(handle.fd),
agl@chromium.org31de02e2009-02-20 11:00:04 +090056 inode_(0),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090057 mapped_size_(0),
avi@google.com3a208982008-08-13 06:06:40 +090058 memory_(NULL),
59 read_only_(read_only),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090060 requested_size_(0) {
agl@chromium.org31de02e2009-02-20 11:00:04 +090061 struct stat st;
62 if (fstat(handle.fd, &st) == 0) {
63 // If fstat fails, then the file descriptor is invalid and we'll learn this
64 // fact when Map() fails.
65 inode_ = st.st_ino;
66 }
avi@google.com3a208982008-08-13 06:06:40 +090067}
68
69SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
70 ProcessHandle process)
agl@chromium.org42bbb992009-02-12 03:59:20 +090071 : mapped_file_(handle.fd),
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +090072 inode_(0),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090073 mapped_size_(0),
avi@google.com3a208982008-08-13 06:06:40 +090074 memory_(NULL),
75 read_only_(read_only),
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +090076 requested_size_(0) {
avi@google.com3a208982008-08-13 06:06:40 +090077 // We don't handle this case yet (note the ignored parameter); let's die if
78 // someone comes calling.
79 NOTREACHED();
80}
81
82SharedMemory::~SharedMemory() {
83 Close();
avi@google.com3a208982008-08-13 06:06:40 +090084}
85
agl@chromium.org42bbb992009-02-12 03:59:20 +090086// static
87bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
88 return handle.fd >= 0;
89}
90
phajdan.jr@chromium.orgfa1476b2009-03-17 01:45:36 +090091// static
92SharedMemoryHandle SharedMemory::NULLHandle() {
93 return SharedMemoryHandle();
94}
95
hclam@chromium.org32300e22009-05-19 02:46:31 +090096// static
97void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
kushi.p@gmail.come4869772011-04-22 22:13:07 +090098 DCHECK_GE(handle.fd, 0);
piman@google.com36c06252011-02-24 06:37:41 +090099 if (HANDLE_EINTR(close(handle.fd)) < 0)
brettw@chromium.org5faed3c2011-10-27 06:48:00 +0900100 DPLOG(ERROR) << "close";
hclam@chromium.org32300e22009-05-19 02:46:31 +0900101}
102
simonjam@chromium.org2afd4062013-05-10 08:15:40 +0900103// static
104size_t SharedMemory::GetHandleLimit() {
105 return base::GetMaxFds();
106}
107
cevans@chromium.org447ba042013-01-10 11:16:24 +0900108bool SharedMemory::CreateAndMapAnonymous(size_t size) {
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900109 return CreateAnonymous(size) && Map(size);
110}
avi@google.com3a208982008-08-13 06:06:40 +0900111
michaelbai@google.com2251c622011-06-22 07:34:50 +0900112#if !defined(OS_ANDROID)
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900113// Chromium mostly only uses the unique/private shmem as specified by
114// "name == L"". The exception is in the StatsTable.
115// TODO(jrg): there is no way to "clean up" all unused named shmem if
116// we restart from a crash. (That isn't a new problem, but it is a problem.)
117// In case we want to delete it later, it may be useful to save the value
118// of mem_filename after FilePathForMemoryName().
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900119bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
mhm@chromium.org73bfc432011-03-01 11:48:05 +0900120 DCHECK_EQ(-1, mapped_file_);
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900121 if (options.size == 0) return false;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900122
cevans@chromium.org447ba042013-01-10 11:16:24 +0900123 if (options.size > static_cast<size_t>(std::numeric_limits<int>::max()))
124 return false;
125
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900126 // This function theoretically can block on the disk, but realistically
127 // the temporary files we create will just go into the buffer cache
128 // and be deleted before they ever make it out to disk.
129 base::ThreadRestrictions::ScopedAllowIO allow_io;
130
131 FILE *fp;
132 bool fix_size = true;
133
134 FilePath path;
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900135 if (options.name == NULL || options.name->empty()) {
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900136 // It doesn't make sense to have a open-existing private piece of shmem
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900137 DCHECK(!options.open_existing);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900138 // Q: Why not use the shm_open() etc. APIs?
139 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU
mcgrathr@chromium.org569a4232011-12-07 03:07:05 +0900140 fp = file_util::CreateAndOpenTemporaryShmemFile(&path, options.executable);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900141
viettrungluu@chromium.orgea7895a2013-02-01 05:17:12 +0900142 // Deleting the file prevents anyone else from mapping it in (making it
143 // private), and prevents the need for cleanup (once the last fd is closed,
144 // it is truly freed).
145 if (fp) {
146 if (unlink(path.value().c_str()))
147 PLOG(WARNING) << "unlink";
148 }
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900149 } else {
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900150 if (!FilePathForMemoryName(*options.name, &path))
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900151 return false;
152
jln@chromium.orge77bef72013-07-03 08:31:55 +0900153 // Make sure that the file is opened without any permission
154 // to other users on the system.
155 const mode_t kOwnerOnly = S_IRUSR | S_IWUSR;
156
157 // First, try to create the file.
158 int fd = HANDLE_EINTR(
159 open(path.value().c_str(), O_RDWR | O_CREAT | O_EXCL, kOwnerOnly));
160 if (fd == -1 && options.open_existing) {
161 // If this doesn't work, try and open an existing file in append mode.
162 // Opening an existing file in a world writable directory has two main
163 // security implications:
164 // - Attackers could plant a file under their control, so ownership of
165 // the file is checked below.
166 // - Attackers could plant a symbolic link so that an unexpected file
167 // is opened, so O_NOFOLLOW is passed to open().
168 fd = HANDLE_EINTR(
169 open(path.value().c_str(), O_RDWR | O_APPEND | O_NOFOLLOW));
170
171 // Check that the current user owns the file.
172 // If uid != euid, then a more complex permission model is used and this
173 // API is not appropriate.
174 const uid_t real_uid = getuid();
175 const uid_t effective_uid = geteuid();
176 struct stat sb;
177 if (fd >= 0 &&
178 (fstat(fd, &sb) != 0 || sb.st_uid != real_uid ||
179 sb.st_uid != effective_uid)) {
180 LOG(ERROR) <<
181 "Invalid owner when opening existing shared memory file.";
182 HANDLE_EINTR(close(fd));
183 return false;
184 }
185
186 // An existing file was opened, so its size should not be fixed.
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900187 fix_size = false;
188 }
jln@chromium.orge77bef72013-07-03 08:31:55 +0900189 fp = NULL;
190 if (fd >= 0) {
191 // "a+" is always appropriate: if it's a new file, a+ is similar to w+.
192 fp = fdopen(fd, "a+");
193 }
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900194 }
195 if (fp && fix_size) {
196 // Get current size.
197 struct stat stat;
gbillock@chromium.org6ee384d2011-06-28 02:24:27 +0900198 if (fstat(fileno(fp), &stat) != 0) {
199 file_util::CloseFile(fp);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900200 return false;
gbillock@chromium.org6ee384d2011-06-28 02:24:27 +0900201 }
cevans@chromium.org447ba042013-01-10 11:16:24 +0900202 const size_t current_size = stat.st_size;
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900203 if (current_size != options.size) {
204 if (HANDLE_EINTR(ftruncate(fileno(fp), options.size)) != 0) {
gbillock@chromium.org6ee384d2011-06-28 02:24:27 +0900205 file_util::CloseFile(fp);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900206 return false;
gbillock@chromium.org6ee384d2011-06-28 02:24:27 +0900207 }
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900208 }
jschuh@chromium.orgc41be7b2013-03-28 11:02:18 +0900209 requested_size_ = options.size;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900210 }
211 if (fp == NULL) {
212#if !defined(OS_MACOSX)
213 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed";
214 FilePath dir = path.DirName();
215 if (access(dir.value().c_str(), W_OK | X_OK) < 0) {
216 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value();
217 if (dir.value() == "/dev/shm") {
218 LOG(FATAL) << "This is frequently caused by incorrect permissions on "
brettw@chromium.org5faed3c2011-10-27 06:48:00 +0900219 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix.";
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900220 }
221 }
222#else
223 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed";
224#endif
agl@chromium.org8c158342008-11-18 09:21:37 +0900225 return false;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900226 }
agl@chromium.org8c158342008-11-18 09:21:37 +0900227
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900228 return PrepareMapFile(fp);
avi@google.com9e0cc152008-08-14 04:59:07 +0900229}
230
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900231// Our current implementation of shmem is with mmap()ing of files.
232// These files need to be deleted explicitly.
233// In practice this call is only needed for unit tests.
evan@chromium.org56756992010-09-30 05:32:22 +0900234bool SharedMemory::Delete(const std::string& name) {
evan@chromium.orgbd3a0d62009-09-17 02:32:11 +0900235 FilePath path;
236 if (!FilePathForMemoryName(name, &path))
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900237 return false;
238
brettw@chromium.org10b64122013-07-12 02:36:07 +0900239 if (PathExists(path))
brettw@chromium.orge9f99482013-07-02 04:41:02 +0900240 return base::Delete(path, false);
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900241
242 // Doesn't exist, so success.
243 return true;
244}
245
evan@chromium.org56756992010-09-30 05:32:22 +0900246bool SharedMemory::Open(const std::string& name, bool read_only) {
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900247 FilePath path;
248 if (!FilePathForMemoryName(name, &path))
249 return false;
250
avi@google.com9e0cc152008-08-14 04:59:07 +0900251 read_only_ = read_only;
agl@chromium.org69e0a492008-11-18 09:21:05 +0900252
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900253 const char *mode = read_only ? "r" : "r+";
254 FILE *fp = file_util::OpenFile(path, mode);
255 return PrepareMapFile(fp);
avi@google.com9e0cc152008-08-14 04:59:07 +0900256}
257
michaelbai@google.com2251c622011-06-22 07:34:50 +0900258#endif // !defined(OS_ANDROID)
259
vitalybuka@chromium.org222e34c2013-01-16 18:02:34 +0900260bool SharedMemory::MapAt(off_t offset, size_t bytes) {
erg@google.com37c078e2011-01-11 09:50:59 +0900261 if (mapped_file_ == -1)
avi@google.com3a208982008-08-13 06:06:40 +0900262 return false;
agl@chromium.org69e0a492008-11-18 09:21:05 +0900263
cevans@chromium.org447ba042013-01-10 11:16:24 +0900264 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
265 return false;
266
michaelbai@google.com2251c622011-06-22 07:34:50 +0900267#if defined(OS_ANDROID)
aelias@chromium.orgd1288092013-03-29 09:10:06 +0900268 // On Android, Map can be called with a size and offset of zero to use the
269 // ashmem-determined size.
michaelbai@google.com2251c622011-06-22 07:34:50 +0900270 if (bytes == 0) {
aelias@chromium.orgd1288092013-03-29 09:10:06 +0900271 DCHECK_EQ(0, offset);
michaelbai@google.com01ef2f22011-07-08 05:46:50 +0900272 int ashmem_bytes = ashmem_get_size_region(mapped_file_);
michaelbai@google.com2251c622011-06-22 07:34:50 +0900273 if (ashmem_bytes < 0)
274 return false;
aelias@chromium.orgd1288092013-03-29 09:10:06 +0900275 bytes = ashmem_bytes;
michaelbai@google.com2251c622011-06-22 07:34:50 +0900276 }
277#endif
278
erg@google.com37c078e2011-01-11 09:50:59 +0900279 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
vitalybuka@chromium.org222e34c2013-01-16 18:02:34 +0900280 MAP_SHARED, mapped_file_, offset);
erg@google.com37c078e2011-01-11 09:50:59 +0900281
raymes@chromium.orgfd41cac2012-04-24 06:00:06 +0900282 bool mmap_succeeded = memory_ != (void*)-1 && memory_ != NULL;
dalecurtis@chromium.org93291932012-08-18 11:17:26 +0900283 if (mmap_succeeded) {
erg@google.com37c078e2011-01-11 09:50:59 +0900284 mapped_size_ = bytes;
dalecurtis@chromium.org93291932012-08-18 11:17:26 +0900285 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
286 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
287 } else {
raymes@chromium.orgfd41cac2012-04-24 06:00:06 +0900288 memory_ = NULL;
dalecurtis@chromium.org93291932012-08-18 11:17:26 +0900289 }
erg@google.com37c078e2011-01-11 09:50:59 +0900290
erg@google.com37c078e2011-01-11 09:50:59 +0900291 return mmap_succeeded;
292}
293
294bool SharedMemory::Unmap() {
295 if (memory_ == NULL)
296 return false;
297
298 munmap(memory_, mapped_size_);
299 memory_ = NULL;
300 mapped_size_ = 0;
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900301 return true;
302}
303
erg@google.com37c078e2011-01-11 09:50:59 +0900304SharedMemoryHandle SharedMemory::handle() const {
305 return FileDescriptor(mapped_file_, false);
306}
307
308void SharedMemory::Close() {
309 Unmap();
310
311 if (mapped_file_ > 0) {
piman@google.com36c06252011-02-24 06:37:41 +0900312 if (HANDLE_EINTR(close(mapped_file_)) < 0)
313 PLOG(ERROR) << "close";
erg@google.com37c078e2011-01-11 09:50:59 +0900314 mapped_file_ = -1;
315 }
316}
317
318void SharedMemory::Lock() {
vandebo@chromium.org439b3d22012-02-25 15:28:56 +0900319 g_thread_lock_.Get().Acquire();
erg@google.com37c078e2011-01-11 09:50:59 +0900320 LockOrUnlockCommon(F_LOCK);
321}
322
323void SharedMemory::Unlock() {
324 LockOrUnlockCommon(F_ULOCK);
vandebo@chromium.org439b3d22012-02-25 15:28:56 +0900325 g_thread_lock_.Get().Release();
erg@google.com37c078e2011-01-11 09:50:59 +0900326}
327
michaelbai@google.com2251c622011-06-22 07:34:50 +0900328#if !defined(OS_ANDROID)
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900329bool SharedMemory::PrepareMapFile(FILE *fp) {
mhm@chromium.org73bfc432011-03-01 11:48:05 +0900330 DCHECK_EQ(-1, mapped_file_);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900331 if (fp == NULL) return false;
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900332
evan@chromium.org7c9cd8b2010-10-23 14:19:20 +0900333 // This function theoretically can block on the disk, but realistically
334 // the temporary files we create will just go into the buffer cache
335 // and be deleted before they ever make it out to disk.
336 base::ThreadRestrictions::ScopedAllowIO allow_io;
337
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900338 file_util::ScopedFILE file_closer(fp);
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900339
340 mapped_file_ = dup(fileno(fp));
stuartmorgan@chromium.org8a8e9662009-06-13 06:15:33 +0900341 if (mapped_file_ == -1) {
342 if (errno == EMFILE) {
343 LOG(WARNING) << "Shared memory creation failed; out of file descriptors";
344 return false;
345 } else {
346 NOTREACHED() << "Call to dup failed, errno=" << errno;
347 }
348 }
agl@chromium.org31de02e2009-02-20 11:00:04 +0900349
350 struct stat st;
351 if (fstat(mapped_file_, &st))
352 NOTREACHED();
353 inode_ = st.st_ino;
354
avi@google.com3a208982008-08-13 06:06:40 +0900355 return true;
356}
michaelbai@google.com2251c622011-06-22 07:34:50 +0900357#endif
avi@google.com3a208982008-08-13 06:06:40 +0900358
erg@google.com37c078e2011-01-11 09:50:59 +0900359// For the given shmem named |mem_name|, return a filename to mmap()
360// (and possibly create). Modifies |filename|. Return false on
361// error, or true of we are happy.
362bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
363 FilePath* path) {
364 // mem_name will be used for a filename; make sure it doesn't
365 // contain anything which will confuse us.
mhm@chromium.org73bfc432011-03-01 11:48:05 +0900366 DCHECK_EQ(std::string::npos, mem_name.find('/'));
367 DCHECK_EQ(std::string::npos, mem_name.find('\0'));
erg@google.com37c078e2011-01-11 09:50:59 +0900368
369 FilePath temp_dir;
mcgrathr@chromium.org569a4232011-12-07 03:07:05 +0900370 if (!file_util::GetShmemTempDir(&temp_dir, false))
avi@google.com3a208982008-08-13 06:06:40 +0900371 return false;
agl@chromium.org69e0a492008-11-18 09:21:05 +0900372
mark@chromium.org13aa8aa2011-04-22 13:15:13 +0900373#if !defined(OS_MACOSX)
374#if defined(GOOGLE_CHROME_BUILD)
375 std::string name_base = std::string("com.google.Chrome");
376#else
377 std::string name_base = std::string("org.chromium.Chromium");
378#endif
379#else // OS_MACOSX
380 std::string name_base = std::string(base::mac::BaseBundleID());
381#endif // OS_MACOSX
382 *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name);
avi@google.com3a208982008-08-13 06:06:40 +0900383 return true;
384}
385
jrg@chromium.org81e22602009-02-06 04:04:34 +0900386void SharedMemory::LockOrUnlockCommon(int function) {
pkasting@chromium.orgd23fe1a2011-04-01 05:34:25 +0900387 DCHECK_GE(mapped_file_, 0);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900388 while (lockf(mapped_file_, function, 0) < 0) {
389 if (errno == EINTR) {
390 continue;
391 } else if (errno == ENOLCK) {
392 // temporary kernel resource exaustion
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900393 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
jrg@chromium.org81e22602009-02-06 04:04:34 +0900394 continue;
395 } else {
396 NOTREACHED() << "lockf() failed."
397 << " function:" << function
398 << " fd:" << mapped_file_
399 << " errno:" << errno
tschmelcher@chromium.org90a3f8a2009-10-14 03:27:40 +0900400 << " msg:" << safe_strerror(errno);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900401 }
avi@google.com3a208982008-08-13 06:06:40 +0900402 }
403}
404
erg@google.com37c078e2011-01-11 09:50:59 +0900405bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
406 SharedMemoryHandle *new_handle,
407 bool close_self) {
408 const int new_fd = dup(mapped_file_);
darin@chromium.org93d40b02012-11-20 15:54:42 +0900409 if (new_fd < 0) {
410 DPLOG(ERROR) << "dup() failed.";
411 return false;
412 }
413
erg@google.com37c078e2011-01-11 09:50:59 +0900414 new_handle->fd = new_fd;
415 new_handle->auto_close = true;
avi@google.com3a208982008-08-13 06:06:40 +0900416
erg@google.com37c078e2011-01-11 09:50:59 +0900417 if (close_self)
418 Close();
license.botf003cfe2008-08-24 09:55:55 +0900419
erg@google.com37c078e2011-01-11 09:50:59 +0900420 return true;
agl@chromium.org42bbb992009-02-12 03:59:20 +0900421}
422
brettw@google.comc60d9892008-11-14 12:25:15 +0900423} // namespace base