• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef BASE_MEMORY_SHARED_MEMORY_H_
6 #define BASE_MEMORY_SHARED_MEMORY_H_
7 
8 #include <stddef.h>
9 
10 #include <string>
11 
12 #include "base/base_export.h"
13 #include "base/macros.h"
14 #include "base/memory/shared_memory_handle.h"
15 #include "base/process/process_handle.h"
16 #include "build/build_config.h"
17 
18 #if defined(OS_POSIX)
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <semaphore.h>
22 #include "base/file_descriptor_posix.h"
23 #include "base/files/file_util.h"
24 #include "base/files/scoped_file.h"
25 #endif
26 
27 #if defined(OS_WIN)
28 #include "base/win/scoped_handle.h"
29 #endif
30 
31 namespace base {
32 
33 class FilePath;
34 
35 // Options for creating a shared memory object.
36 struct BASE_EXPORT SharedMemoryCreateOptions {
37 #if defined(OS_MACOSX) && !defined(OS_IOS)
38   // The type of OS primitive that should back the SharedMemory object.
39   SharedMemoryHandle::Type type = SharedMemoryHandle::MACH;
40 #else
41   // DEPRECATED (crbug.com/345734):
42   // If NULL, the object is anonymous.  This pointer is owned by the caller
43   // and must live through the call to Create().
44   const std::string* name_deprecated = nullptr;
45 
46   // DEPRECATED (crbug.com/345734):
47   // If true, and the shared memory already exists, Create() will open the
48   // existing shared memory and ignore the size parameter.  If false,
49   // shared memory must not exist.  This flag is meaningless unless
50   // name_deprecated is non-NULL.
51   bool open_existing_deprecated = false;
52 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
53 
54   // Size of the shared memory object to be created.
55   // When opening an existing object, this has no effect.
56   size_t size = 0;
57 
58   // If true, mappings might need to be made executable later.
59   bool executable = false;
60 
61   // If true, the file can be shared read-only to a process.
62   bool share_read_only = false;
63 };
64 
65 // Platform abstraction for shared memory.  Provides a C++ wrapper
66 // around the OS primitive for a memory mapped file.
67 class BASE_EXPORT SharedMemory {
68  public:
69   SharedMemory();
70 
71 #if defined(OS_WIN)
72   // Similar to the default constructor, except that this allows for
73   // calling LockDeprecated() to acquire the named mutex before either Create or
74   // Open are called on Windows.
75   explicit SharedMemory(const std::wstring& name);
76 #endif
77 
78   // Create a new SharedMemory object from an existing, open
79   // shared memory file.
80   //
81   // WARNING: This does not reduce the OS-level permissions on the handle; it
82   // only affects how the SharedMemory will be mmapped.  Use
83   // ShareReadOnlyToProcess to drop permissions.  TODO(jln,jyasskin): DCHECK
84   // that |read_only| matches the permissions of the handle.
85   SharedMemory(const SharedMemoryHandle& handle, bool read_only);
86 
87   // Closes any open files.
88   ~SharedMemory();
89 
90   // Return true iff the given handle is valid (i.e. not the distingished
91   // invalid value; NULL for a HANDLE and -1 for a file descriptor)
92   static bool IsHandleValid(const SharedMemoryHandle& handle);
93 
94   // Returns invalid handle (see comment above for exact definition).
95   static SharedMemoryHandle NULLHandle();
96 
97   // Closes a shared memory handle.
98   static void CloseHandle(const SharedMemoryHandle& handle);
99 
100   // Returns the maximum number of handles that can be open at once per process.
101   static size_t GetHandleLimit();
102 
103   // Duplicates The underlying OS primitive. Returns NULLHandle() on failure.
104   // The caller is responsible for destroying the duplicated OS primitive.
105   static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle);
106 
107 #if defined(OS_POSIX)
108   // This method requires that the SharedMemoryHandle is backed by a POSIX fd.
109   static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle);
110 #endif
111 
112 #if defined(OS_POSIX) && !defined(OS_ANDROID)
113   // Gets the size of the shared memory region referred to by |handle|.
114   // Returns false on a failure to determine the size. On success, populates the
115   // output variable |size|.
116   static bool GetSizeFromSharedMemoryHandle(const SharedMemoryHandle& handle,
117                                             size_t* size);
118 #endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
119 
120   // Creates a shared memory object as described by the options struct.
121   // Returns true on success and false on failure.
122   bool Create(const SharedMemoryCreateOptions& options);
123 
124   // Creates and maps an anonymous shared memory segment of size size.
125   // Returns true on success and false on failure.
126   bool CreateAndMapAnonymous(size_t size);
127 
128   // Creates an anonymous shared memory segment of size size.
129   // Returns true on success and false on failure.
CreateAnonymous(size_t size)130   bool CreateAnonymous(size_t size) {
131     SharedMemoryCreateOptions options;
132     options.size = size;
133     return Create(options);
134   }
135 
136 #if !defined(OS_MACOSX) || defined(OS_IOS)
137   // DEPRECATED (crbug.com/345734):
138   // Creates or opens a shared memory segment based on a name.
139   // If open_existing is true, and the shared memory already exists,
140   // opens the existing shared memory and ignores the size parameter.
141   // If open_existing is false, shared memory must not exist.
142   // size is the size of the block to be created.
143   // Returns true on success, false on failure.
CreateNamedDeprecated(const std::string & name,bool open_existing,size_t size)144   bool CreateNamedDeprecated(
145       const std::string& name, bool open_existing, size_t size) {
146     SharedMemoryCreateOptions options;
147     options.name_deprecated = &name;
148     options.open_existing_deprecated = open_existing;
149     options.size = size;
150     return Create(options);
151   }
152 
153   // Deletes resources associated with a shared memory segment based on name.
154   // Not all platforms require this call.
155   bool Delete(const std::string& name);
156 
157   // Opens a shared memory segment based on a name.
158   // If read_only is true, opens for read-only access.
159   // Returns true on success, false on failure.
160   bool Open(const std::string& name, bool read_only);
161 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
162 
163   // Maps the shared memory into the caller's address space.
164   // Returns true on success, false otherwise.  The memory address
165   // is accessed via the memory() accessor.  The mapped address is guaranteed to
166   // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail
167   // if this object is currently mapped.
Map(size_t bytes)168   bool Map(size_t bytes) {
169     return MapAt(0, bytes);
170   }
171 
172   // Same as above, but with |offset| to specify from begining of the shared
173   // memory block to map.
174   // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|.
175   bool MapAt(off_t offset, size_t bytes);
176   enum { MAP_MINIMUM_ALIGNMENT = 32 };
177 
178   // Unmaps the shared memory from the caller's address space.
179   // Returns true if successful; returns false on error or if the
180   // memory is not mapped.
181   bool Unmap();
182 
183   // The size requested when the map is first created.
requested_size()184   size_t requested_size() const { return requested_size_; }
185 
186   // The actual size of the mapped memory (may be larger than requested).
mapped_size()187   size_t mapped_size() const { return mapped_size_; }
188 
189   // Gets a pointer to the opened memory space if it has been
190   // Mapped via Map().  Returns NULL if it is not mapped.
memory()191   void* memory() const { return memory_; }
192 
193   // Returns the underlying OS handle for this segment.
194   // Use of this handle for anything other than an opaque
195   // identifier is not portable.
196   SharedMemoryHandle handle() const;
197 
198   // Returns the underlying OS handle for this segment. The caller also gets
199   // ownership of the handle. This is logically equivalent to:
200   //   SharedMemoryHandle dup = DuplicateHandle(handle());
201   //   Close();
202   //   return dup;
203   SharedMemoryHandle TakeHandle();
204 
205   // Closes the open shared memory segment. The memory will remain mapped if
206   // it was previously mapped.
207   // It is safe to call Close repeatedly.
208   void Close();
209 
210   // Shares the shared memory to another process.  Attempts to create a
211   // platform-specific new_handle which can be used in a remote process to read
212   // the shared memory file.  new_handle is an output parameter to receive the
213   // handle for use in the remote process.
214   //
215   // |*this| must have been initialized using one of the Create*() or Open()
216   // methods with share_read_only=true. If it was constructed from a
217   // SharedMemoryHandle, this call will CHECK-fail.
218   //
219   // Returns true on success, false otherwise.
ShareReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)220   bool ShareReadOnlyToProcess(ProcessHandle process,
221                               SharedMemoryHandle* new_handle) {
222     return ShareToProcessCommon(process, new_handle, false, SHARE_READONLY);
223   }
224 
225   // Logically equivalent to:
226   //   bool ok = ShareReadOnlyToProcess(process, new_handle);
227   //   Close();
228   //   return ok;
229   // Note that the memory is unmapped by calling this method, regardless of the
230   // return value.
GiveReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)231   bool GiveReadOnlyToProcess(ProcessHandle process,
232                              SharedMemoryHandle* new_handle) {
233     return ShareToProcessCommon(process, new_handle, true, SHARE_READONLY);
234   }
235 
236   // Shares the shared memory to another process.  Attempts
237   // to create a platform-specific new_handle which can be
238   // used in a remote process to access the shared memory
239   // file.  new_handle is an output parameter to receive
240   // the handle for use in the remote process.
241   // Returns true on success, false otherwise.
ShareToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)242   bool ShareToProcess(ProcessHandle process,
243                       SharedMemoryHandle* new_handle) {
244     return ShareToProcessCommon(process, new_handle, false, SHARE_CURRENT_MODE);
245   }
246 
247   // Logically equivalent to:
248   //   bool ok = ShareToProcess(process, new_handle);
249   //   Close();
250   //   return ok;
251   // Note that the memory is unmapped by calling this method, regardless of the
252   // return value.
GiveToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)253   bool GiveToProcess(ProcessHandle process,
254                      SharedMemoryHandle* new_handle) {
255     return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE);
256   }
257 
258 #if defined(OS_POSIX) && (!defined(OS_MACOSX) || defined(OS_IOS)) && \
259     !defined(OS_NACL)
260   using UniqueId = std::pair<dev_t, ino_t>;
261 
262   struct UniqueIdHash {
operatorUniqueIdHash263     size_t operator()(const UniqueId& id) const {
264       return HashInts(id.first, id.second);
265     }
266   };
267 
268   // Returns a unique ID for this shared memory's handle. Note this function may
269   // access file system and be slow.
270   bool GetUniqueId(UniqueId* id) const;
271 #endif
272 
273  private:
274 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \
275     (!defined(OS_MACOSX) || defined(OS_IOS))
276   bool FilePathForMemoryName(const std::string& mem_name, FilePath* path);
277 #endif
278 
279   enum ShareMode {
280     SHARE_READONLY,
281     SHARE_CURRENT_MODE,
282   };
283 
284 #if defined(OS_MACOSX)
285   bool Share(SharedMemoryHandle* new_handle, ShareMode share_mode);
286 #endif
287 
288   bool ShareToProcessCommon(ProcessHandle process,
289                             SharedMemoryHandle* new_handle,
290                             bool close_self,
291                             ShareMode);
292 
293 #if defined(OS_WIN)
294   // If true indicates this came from an external source so needs extra checks
295   // before being mapped.
296   bool external_section_;
297   std::wstring       name_;
298   win::ScopedHandle  mapped_file_;
299 #elif defined(OS_MACOSX) && !defined(OS_IOS)
300   // The OS primitive that backs the shared memory region.
301   SharedMemoryHandle shm_;
302 
303   // The mechanism by which the memory is mapped. Only valid if |memory_| is not
304   // |nullptr|.
305   SharedMemoryHandle::Type mapped_memory_mechanism_;
306 
307   int readonly_mapped_file_;
308 #elif defined(OS_POSIX)
309   int                mapped_file_;
310   int                readonly_mapped_file_;
311 #endif
312   size_t             mapped_size_;
313   void*              memory_;
314   bool               read_only_;
315   size_t             requested_size_;
316 
317   DISALLOW_COPY_AND_ASSIGN(SharedMemory);
318 };
319 
320 }  // namespace base
321 
322 #endif  // BASE_MEMORY_SHARED_MEMORY_H_
323