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

Side by Side Diff: base/shared_memory_posix.cc

Issue 19724: Properly honor base::SharedMemory semantics for name="" to mean... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 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
« no previous file with comments | « base/shared_memory.h ('k') | base/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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 10
11 #include "base/file_util.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 14
14 namespace base { 15 namespace base {
15 16
16 namespace { 17 namespace {
17 // Paranoia. Semaphores and shared memory segments should live in different 18 // Paranoia. Semaphores and shared memory segments should live in different
18 // namespaces, but who knows what's out there. 19 // namespaces, but who knows what's out there.
19 const char kSemaphoreSuffix[] = "-sem"; 20 const char kSemaphoreSuffix[] = "-sem";
20 } 21 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 56
56 bool SharedMemory::Create(const std::wstring &name, bool read_only, 57 bool SharedMemory::Create(const std::wstring &name, bool read_only,
57 bool open_existing, size_t size) { 58 bool open_existing, size_t size) {
58 read_only_ = read_only; 59 read_only_ = read_only;
59 60
60 int posix_flags = 0; 61 int posix_flags = 0;
61 posix_flags |= read_only ? O_RDONLY : O_RDWR; 62 posix_flags |= read_only ? O_RDONLY : O_RDWR;
62 if (!open_existing || mapped_file_ <= 0) 63 if (!open_existing || mapped_file_ <= 0)
63 posix_flags |= O_CREAT; 64 posix_flags |= O_CREAT;
64 65
65 if (!CreateOrOpen(name, posix_flags)) 66 if (!CreateOrOpen(name, posix_flags, size))
66 return false; 67 return false;
67 68
68 if (ftruncate(mapped_file_, size) != 0) {
69 Close();
70 return false;
71 }
72
73 max_size_ = size; 69 max_size_ = size;
74 return true; 70 return true;
75 } 71 }
76 72
73 // Our current implementation of shmem is with mmap()ing of files.
74 // These files need to be deleted explicitly.
75 // In practice this call is only needed for unit tests.
76 bool SharedMemory::Delete(const std::wstring& name) {
77 std::wstring mem_filename;
78 if (FilenameForMemoryName(name, &mem_filename) == false)
79 return false;
80
81 FilePath path(WideToUTF8(mem_filename));
82 if (file_util::PathExists(path)) {
83 return file_util::Delete(path, false);
84 }
85
86 // Doesn't exist, so success.
87 return true;
88 }
89
77 bool SharedMemory::Open(const std::wstring &name, bool read_only) { 90 bool SharedMemory::Open(const std::wstring &name, bool read_only) {
78 read_only_ = read_only; 91 read_only_ = read_only;
79 92
80 int posix_flags = 0; 93 int posix_flags = 0;
81 posix_flags |= read_only ? O_RDONLY : O_RDWR; 94 posix_flags |= read_only ? O_RDONLY : O_RDWR;
82 95
83 return CreateOrOpen(name, posix_flags); 96 return CreateOrOpen(name, posix_flags, 0);
84 } 97 }
85 98
86 bool SharedMemory::CreateOrOpen(const std::wstring &name, int posix_flags) { 99 // For the given shmem named |memname|, return a filename to mmap()
100 // (and possibly create). Modifies |filename|. Return false on
101 // error, or true of we are happy.
102 bool SharedMemory::FilenameForMemoryName(const std::wstring &memname,
103 std::wstring *filename) {
104 std::wstring mem_filename;
105
106 // mem_name will be used for a filename; make sure it doesn't
107 // contain anything which will confuse us.
108 DCHECK(memname.find_first_of(L"/") == std::string::npos);
109 DCHECK(memname.find_first_of(L"\0") == std::string::npos);
110
111 FilePath temp_dir;
112 if (file_util::GetShmemTempDir(&temp_dir) == false)
113 return false;
114
115 mem_filename = UTF8ToWide(temp_dir.value());
116 file_util::AppendToPath(&mem_filename, L"com.google.chrome.shmem." + memname);
117 *filename = mem_filename;
118 return true;
119 }
120
121 // Current expectation is that Cromium only really needs
122 // unique/private shmem as specified by "name == L"".
123 // TODO(port): confirm that assumption.
124 // TODO(jrg): there is no way to "clean up" all unused named shmem if
125 // we restart from a crash. (That isn't a new problem, but it is a problem.)
126 bool SharedMemory::CreateOrOpen(const std::wstring &name,
127 int posix_flags, size_t size) {
87 DCHECK(mapped_file_ == -1); 128 DCHECK(mapped_file_ == -1);
88 129
89 name_ = L"/" + name; 130 file_util::ScopedFILE file_closer;
131 FILE *fp;
90 132
91 mode_t posix_mode = S_IRUSR | S_IWUSR; // owner read/write 133 if (name == L"") {
92 std::string posix_name(WideToUTF8(name_)); 134 // It doesn't make sense to have a read-only private piece of shmem
93 mapped_file_ = shm_open(posix_name.c_str(), posix_flags, posix_mode); 135 DCHECK(posix_flags & (O_RDWR | O_WRONLY));
94 if (mapped_file_ < 0) 136
137 FilePath path;
138 fp = file_util::CreateAndOpenTemporaryShmemFile(&path);
139 name_ = UTF8ToWide(path.value());
140
141 // Deleting the file prevents anyone else from mapping it in
142 // (making it private), and prevents the need for cleanup (once
143 // the last fd is closed, it is truly freed).
144 file_util::Delete(path, false);
145 } else {
146 std::wstring mem_filename;
147 if (FilenameForMemoryName(name, &mem_filename) == false)
148 return false;
149
150 name_ = mem_filename;
151 std::string mode;
152 switch (posix_flags) {
153 case (O_RDWR | O_CREAT):
154 // Careful: "w+" will truncate if it already exists.
155 mode = "a+";
156 break;
157 case O_RDWR:
158 mode = "r+";
159 break;
160 case O_RDONLY:
161 mode = "r";
162 break;
163 default:
164 NOTIMPLEMENTED();
165 break;
166 }
167
168 fp = file_util::OpenFile(mem_filename, mode.c_str());
169 }
170
171 if (fp == NULL)
95 return false; 172 return false;
173 file_closer.reset(fp); // close when we go out of scope
96 174
97 posix_name += kSemaphoreSuffix; 175 // Make sure the (new) file is the right size.
98 lock_ = sem_open(posix_name.c_str(), O_CREAT, posix_mode, 1); 176 // According to the man page, "Use of truncate() to extend a file is
177 // not portable."
178 if (size && (posix_flags & (O_RDWR | O_CREAT))) {
179 // Get current size.
180 size_t current_size = 0;
181 struct stat stat;
182 if (fstat(fileno(fp), &stat) != 0)
183 return false;
184 current_size = stat.st_size;
185 // Possibly grow.
186 if (current_size < size) {
187 if (fseeko(fp, current_size, SEEK_SET) != 0)
188 return false;
189 size_t writesize = size - current_size;
190 scoped_array<char> buf(new char[writesize]);
191 memset(buf.get(), 0, writesize);
192 if (fwrite(buf.get(), 1, writesize, fp) != writesize) {
193 return false;
194 }
195 if (fflush(fp) != 0)
196 return false;
197 } else if (current_size > size) {
198 // possibly shrink.
199 if ((ftruncate(fileno(fp), size) != 0) ||
200 (fflush(fp) != 0)) {
201 return false;
202 }
203 }
204 }
205
206 mapped_file_ = dup(fileno(fp));
207 DCHECK(mapped_file_ >= 0);
208
209 mode_t posix_mode = S_IRUSR | S_IWUSR; // owner read/write
210 // name_ that includes a tmpdir easily exceeds SEM_NAME_LEN,
211 // so we cannot use it directly as the basis for a sem_name_.
212 sem_name_ = WideToUTF8(name) + kSemaphoreSuffix;
213 lock_ = sem_open(sem_name_.c_str(), O_CREAT, posix_mode, 1);
99 if (lock_ == SEM_FAILED) { 214 if (lock_ == SEM_FAILED) {
100 close(mapped_file_); 215 close(mapped_file_);
101 mapped_file_ = -1; 216 mapped_file_ = -1;
102 shm_unlink(posix_name.c_str());
103 lock_ = NULL; 217 lock_ = NULL;
104 return false; 218 return false;
105 } 219 }
106 220
107 return true; 221 return true;
108 } 222 }
109 223
110 bool SharedMemory::Map(size_t bytes) { 224 bool SharedMemory::Map(size_t bytes) {
111 if (mapped_file_ == -1) 225 if (mapped_file_ == -1)
112 return false; 226 return false;
(...skipping 27 matching lines...) Expand all
140 } 254 }
141 255
142 256
143 void SharedMemory::Close() { 257 void SharedMemory::Close() {
144 258
145 Unmap(); 259 Unmap();
146 260
147 std::string posix_name(WideToUTF8(name_)); 261 std::string posix_name(WideToUTF8(name_));
148 if (mapped_file_ > 0) { 262 if (mapped_file_ > 0) {
149 close(mapped_file_); 263 close(mapped_file_);
150 shm_unlink(posix_name.c_str());
151 mapped_file_ = -1; 264 mapped_file_ = -1;
152 } 265 }
153 266
154 if (lock_) { 267 if (lock_) {
155 posix_name += kSemaphoreSuffix; 268 sem_unlink(sem_name_.c_str());
156 sem_unlink(posix_name.c_str());
157 lock_ = NULL; 269 lock_ = NULL;
158 } 270 }
159 } 271 }
160 272
161 void SharedMemory::Lock() { 273 void SharedMemory::Lock() {
162 DCHECK(lock_ != NULL); 274 DCHECK(lock_ != NULL);
163 while(sem_wait(lock_) < 0) { 275 while(sem_wait(lock_) < 0) {
164 DCHECK(errno == EAGAIN || errno == EINTR); 276 DCHECK(errno == EAGAIN || errno == EINTR);
165 } 277 }
166 } 278 }
167 279
168 void SharedMemory::Unlock() { 280 void SharedMemory::Unlock() {
169 DCHECK(lock_ != NULL); 281 DCHECK(lock_ != NULL);
170 int result = sem_post(lock_); 282 int result = sem_post(lock_);
171 DCHECK(result == 0); 283 DCHECK(result == 0);
172 } 284 }
173 285
174 } // namespace base 286 } // namespace base
OLDNEW
« no previous file with comments | « base/shared_memory.h ('k') | base/shared_memory_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698