OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { | 91 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { |
92 DCHECK_GE(handle.fd, 0); | 92 DCHECK_GE(handle.fd, 0); |
93 if (HANDLE_EINTR(close(handle.fd)) < 0) | 93 if (HANDLE_EINTR(close(handle.fd)) < 0) |
94 DPLOG(ERROR) << "close"; | 94 DPLOG(ERROR) << "close"; |
95 } | 95 } |
96 | 96 |
97 bool SharedMemory::CreateAndMapAnonymous(uint32 size) { | 97 bool SharedMemory::CreateAndMapAnonymous(uint32 size) { |
98 return CreateAnonymous(size) && Map(size); | 98 return CreateAnonymous(size) && Map(size); |
99 } | 99 } |
100 | 100 |
101 bool SharedMemory::CreateAnonymous(uint32 size) { | |
102 return CreateNamed("", false, size); | |
103 } | |
104 | |
105 #if !defined(OS_ANDROID) | 101 #if !defined(OS_ANDROID) |
106 // Chromium mostly only uses the unique/private shmem as specified by | 102 // Chromium mostly only uses the unique/private shmem as specified by |
107 // "name == L"". The exception is in the StatsTable. | 103 // "name == L"". The exception is in the StatsTable. |
108 // TODO(jrg): there is no way to "clean up" all unused named shmem if | 104 // TODO(jrg): there is no way to "clean up" all unused named shmem if |
109 // we restart from a crash. (That isn't a new problem, but it is a problem.) | 105 // we restart from a crash. (That isn't a new problem, but it is a problem.) |
110 // In case we want to delete it later, it may be useful to save the value | 106 // In case we want to delete it later, it may be useful to save the value |
111 // of mem_filename after FilePathForMemoryName(). | 107 // of mem_filename after FilePathForMemoryName(). |
112 bool SharedMemory::CreateNamed(const std::string& name, | 108 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
113 bool open_existing, uint32 size) { | |
114 DCHECK_EQ(-1, mapped_file_); | 109 DCHECK_EQ(-1, mapped_file_); |
115 if (size == 0) return false; | 110 if (options.size == 0) return false; |
116 | 111 |
117 // This function theoretically can block on the disk, but realistically | 112 // This function theoretically can block on the disk, but realistically |
118 // the temporary files we create will just go into the buffer cache | 113 // the temporary files we create will just go into the buffer cache |
119 // and be deleted before they ever make it out to disk. | 114 // and be deleted before they ever make it out to disk. |
120 base::ThreadRestrictions::ScopedAllowIO allow_io; | 115 base::ThreadRestrictions::ScopedAllowIO allow_io; |
121 | 116 |
122 FILE *fp; | 117 FILE *fp; |
123 bool fix_size = true; | 118 bool fix_size = true; |
124 | 119 |
125 FilePath path; | 120 FilePath path; |
126 if (name.empty()) { | 121 if (options.name == NULL || options.name->empty()) { |
127 // It doesn't make sense to have a open-existing private piece of shmem | 122 // It doesn't make sense to have a open-existing private piece of shmem |
128 DCHECK(!open_existing); | 123 DCHECK(!options.open_existing); |
129 // Q: Why not use the shm_open() etc. APIs? | 124 // Q: Why not use the shm_open() etc. APIs? |
130 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU | 125 // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU |
131 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); | 126 fp = file_util::CreateAndOpenTemporaryShmemFile(&path); |
132 | 127 |
133 // Deleting the file prevents anyone else from mapping it in | 128 // Deleting the file prevents anyone else from mapping it in |
134 // (making it private), and prevents the need for cleanup (once | 129 // (making it private), and prevents the need for cleanup (once |
135 // the last fd is closed, it is truly freed). | 130 // the last fd is closed, it is truly freed). |
136 if (fp) | 131 if (fp) |
137 file_util::Delete(path, false); | 132 file_util::Delete(path, false); |
138 | 133 |
139 } else { | 134 } else { |
140 if (!FilePathForMemoryName(name, &path)) | 135 if (!FilePathForMemoryName(*options.name, &path)) |
141 return false; | 136 return false; |
142 | 137 |
143 fp = file_util::OpenFile(path, "w+x"); | 138 fp = file_util::OpenFile(path, "w+x"); |
144 if (fp == NULL && open_existing) { | 139 if (fp == NULL && options.open_existing) { |
145 // "w+" will truncate if it already exists. | 140 // "w+" will truncate if it already exists. |
146 fp = file_util::OpenFile(path, "a+"); | 141 fp = file_util::OpenFile(path, "a+"); |
147 fix_size = false; | 142 fix_size = false; |
148 } | 143 } |
149 } | 144 } |
150 if (fp && fix_size) { | 145 if (fp && fix_size) { |
151 // Get current size. | 146 // Get current size. |
152 struct stat stat; | 147 struct stat stat; |
153 if (fstat(fileno(fp), &stat) != 0) { | 148 if (fstat(fileno(fp), &stat) != 0) { |
154 file_util::CloseFile(fp); | 149 file_util::CloseFile(fp); |
155 return false; | 150 return false; |
156 } | 151 } |
157 const uint32 current_size = stat.st_size; | 152 const uint32 current_size = stat.st_size; |
158 if (current_size != size) { | 153 if (current_size != options.size) { |
159 if (HANDLE_EINTR(ftruncate(fileno(fp), size)) != 0) { | 154 if (HANDLE_EINTR(ftruncate(fileno(fp), options.size)) != 0) { |
160 file_util::CloseFile(fp); | 155 file_util::CloseFile(fp); |
161 return false; | 156 return false; |
162 } | 157 } |
163 if (fseeko(fp, size, SEEK_SET) != 0) { | 158 if (fseeko(fp, options.size, SEEK_SET) != 0) { |
164 file_util::CloseFile(fp); | 159 file_util::CloseFile(fp); |
165 return false; | 160 return false; |
166 } | 161 } |
167 } | 162 } |
168 created_size_ = size; | 163 created_size_ = options.size; |
169 } | 164 } |
170 if (fp == NULL) { | 165 if (fp == NULL) { |
171 #if !defined(OS_MACOSX) | 166 #if !defined(OS_MACOSX) |
172 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; | 167 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; |
173 FilePath dir = path.DirName(); | 168 FilePath dir = path.DirName(); |
174 if (access(dir.value().c_str(), W_OK | X_OK) < 0) { | 169 if (access(dir.value().c_str(), W_OK | X_OK) < 0) { |
175 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); | 170 PLOG(ERROR) << "Unable to access(W_OK|X_OK) " << dir.value(); |
176 if (dir.value() == "/dev/shm") { | 171 if (dir.value() == "/dev/shm") { |
177 LOG(FATAL) << "This is frequently caused by incorrect permissions on " | 172 LOG(FATAL) << "This is frequently caused by incorrect permissions on " |
178 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; | 173 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 new_handle->fd = new_fd; | 360 new_handle->fd = new_fd; |
366 new_handle->auto_close = true; | 361 new_handle->auto_close = true; |
367 | 362 |
368 if (close_self) | 363 if (close_self) |
369 Close(); | 364 Close(); |
370 | 365 |
371 return true; | 366 return true; |
372 } | 367 } |
373 | 368 |
374 } // namespace base | 369 } // namespace base |
OLD | NEW |