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

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

Issue 1421933002: Revert of mac: Add auto-close and share-read-only functionality to SharedMemory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « base/memory/shared_memory_mac.cc ('k') | ipc/attachment_broker_mac_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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 <mach/mach.h> 5 #include <mach/mach.h>
6 #include <mach/mach_vm.h> 6 #include <mach/mach_vm.h>
7 #include <servers/bootstrap.h> 7 #include <servers/bootstrap.h>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/mac/mac_util.h"
11 #include "base/mac/mach_logging.h" 10 #include "base/mac/mach_logging.h"
12 #include "base/mac/scoped_mach_port.h" 11 #include "base/mac/scoped_mach_port.h"
13 #include "base/memory/shared_memory.h" 12 #include "base/memory/shared_memory.h"
14 #include "base/process/process_handle.h" 13 #include "base/process/process_handle.h"
15 #include "base/rand_util.h" 14 #include "base/rand_util.h"
16 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
17 #include "base/sys_info.h" 16 #include "base/sys_info.h"
18 #include "base/test/multiprocess_test.h" 17 #include "base/test/multiprocess_test.h"
19 #include "base/test/test_timeouts.h" 18 #include "base/test/test_timeouts.h"
20 #include "testing/multiprocess_func_list.h" 19 #include "testing/multiprocess_func_list.h"
21 20
22 namespace base { 21 namespace base {
23 22
24 namespace { 23 namespace {
25 24
26 // Gets the current and maximum protection levels of the memory region.
27 // Returns whether the operation was successful.
28 // |current| and |max| are output variables only populated on success.
29 bool GetProtections(void* address, size_t size, int* current, int* max) {
30 vm_region_info_t region_info;
31 mach_vm_address_t mem_address = reinterpret_cast<mach_vm_address_t>(address);
32 mach_vm_size_t mem_size = size;
33 vm_region_basic_info_64 basic_info;
34
35 region_info = reinterpret_cast<vm_region_recurse_info_t>(&basic_info);
36 vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64;
37 memory_object_name_t memory_object;
38 mach_port_t ctype;
39
40 kern_return_t kr =
41 mach_vm_region(mach_task_self(), &mem_address, &mem_size, flavor,
42 region_info, &memory_object, &ctype);
43 if (kr != KERN_SUCCESS) {
44 LOG(ERROR) << "Failed to get region info.";
45 return false;
46 }
47
48 *current = basic_info.protection;
49 *max = basic_info.max_protection;
50 return true;
51 }
52
53 // Creates a new SharedMemory with the given |size|, filled with 'a'.
54 scoped_ptr<SharedMemory> CreateSharedMemory(int size) {
55 SharedMemoryHandle shm(size);
56 if (!shm.IsValid()) {
57 LOG(ERROR) << "Failed to make SharedMemoryHandle";
58 return nullptr;
59 }
60 scoped_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false));
61 shared_memory->Map(size);
62 memset(shared_memory->memory(), 'a', size);
63 return shared_memory;
64 }
65
66 static const std::string g_service_switch_name = "service_name"; 25 static const std::string g_service_switch_name = "service_name";
67 26
68 // Structs used to pass a mach port from client to server. 27 // Structs used to pass a mach port from client to server.
69 struct MachSendPortMessage { 28 struct MachSendPortMessage {
70 mach_msg_header_t header; 29 mach_msg_header_t header;
71 mach_msg_body_t body; 30 mach_msg_body_t body;
72 mach_msg_port_descriptor_t data; 31 mach_msg_port_descriptor_t data;
73 }; 32 };
74 struct MachReceivePortMessage { 33 struct MachReceivePortMessage {
75 mach_msg_header_t header; 34 mach_msg_header_t header;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 // process. 177 // process.
219 mac::ScopedMachSendRight client_port_; 178 mac::ScopedMachSendRight client_port_;
220 179
221 base::Process child_process_; 180 base::Process child_process_;
222 DISALLOW_COPY_AND_ASSIGN(SharedMemoryMacMultiProcessTest); 181 DISALLOW_COPY_AND_ASSIGN(SharedMemoryMacMultiProcessTest);
223 }; 182 };
224 183
225 // Tests that content written to shared memory in the server process can be read 184 // Tests that content written to shared memory in the server process can be read
226 // by the child process. 185 // by the child process.
227 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) { 186 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) {
228 // Mach-based SharedMemory isn't support on OSX 10.6.
229 if (mac::IsOSSnowLeopard())
230 return;
231
232 SetUpChild("MachBasedSharedMemoryClient"); 187 SetUpChild("MachBasedSharedMemoryClient");
233 188
234 scoped_ptr<SharedMemory> shared_memory( 189 SharedMemoryHandle shm(s_memory_size);
235 CreateSharedMemory(s_memory_size).Pass()); 190 ASSERT_TRUE(shm.IsValid());
191 SharedMemory shared_memory(shm, false);
192 shared_memory.Map(s_memory_size);
193 memset(shared_memory.memory(), 'a', s_memory_size);
236 194
237 // Send the underlying memory object to the client process. 195 // Send the underlying memory object to the client process.
238 SendMachPort(client_port_.get(), shared_memory->handle().GetMemoryObject(), 196 SendMachPort(
239 MACH_MSG_TYPE_COPY_SEND); 197 client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND);
240 int rv = -1; 198 int rv = -1;
241 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( 199 ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
242 TestTimeouts::action_timeout(), &rv)); 200 TestTimeouts::action_timeout(), &rv));
243 EXPECT_EQ(0, rv); 201 EXPECT_EQ(0, rv);
244 } 202 }
245 203
246 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) { 204 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) {
247 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); 205 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp());
248 // The next mach port should be for a memory object. 206 // The next mach port should be for a memory object.
249 mach_port_t memory_object = ReceiveMachPort(client_port.get()); 207 mach_port_t memory_object = ReceiveMachPort(client_port.get());
250 SharedMemoryHandle shm(memory_object, 208 SharedMemoryHandle shm(memory_object,
251 SharedMemoryMacMultiProcessTest::s_memory_size, 209 SharedMemoryMacMultiProcessTest::s_memory_size,
252 GetCurrentProcId()); 210 GetCurrentProcId());
253 SharedMemory shared_memory(shm, false); 211 SharedMemory shared_memory(shm, false);
254 shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size); 212 shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size);
255 const char* start = static_cast<const char*>(shared_memory.memory()); 213 const char* start = static_cast<const char*>(shared_memory.memory());
256 for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) { 214 for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) {
257 DCHECK_EQ(start[i], 'a'); 215 DCHECK_EQ(start[i], 'a');
258 } 216 }
259 return 0; 217 return 0;
260 } 218 }
261 219
262 // Tests that mapping shared memory with an offset works correctly. 220 // Tests that mapping shared memory with an offset works correctly.
263 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) { 221 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) {
264 // Mach-based SharedMemory isn't support on OSX 10.6.
265 if (mac::IsOSSnowLeopard())
266 return;
267
268 SetUpChild("MachBasedSharedMemoryWithOffsetClient"); 222 SetUpChild("MachBasedSharedMemoryWithOffsetClient");
269 223
270 SharedMemoryHandle shm(s_memory_size); 224 SharedMemoryHandle shm(s_memory_size);
271 ASSERT_TRUE(shm.IsValid()); 225 ASSERT_TRUE(shm.IsValid());
272 SharedMemory shared_memory(shm, false); 226 SharedMemory shared_memory(shm, false);
273 shared_memory.Map(s_memory_size); 227 shared_memory.Map(s_memory_size);
274 228
275 size_t page_size = SysInfo::VMAllocationGranularity(); 229 size_t page_size = SysInfo::VMAllocationGranularity();
276 char* start = static_cast<char*>(shared_memory.memory()); 230 char* start = static_cast<char*>(shared_memory.memory());
277 memset(start, 'a', page_size); 231 memset(start, 'a', page_size);
(...skipping 25 matching lines...) Expand all
303 } 257 }
304 for (size_t i = page_size; i < 2 * page_size; ++i) { 258 for (size_t i = page_size; i < 2 * page_size; ++i) {
305 DCHECK_EQ(start[i], 'c'); 259 DCHECK_EQ(start[i], 'c');
306 } 260 }
307 return 0; 261 return 0;
308 } 262 }
309 263
310 // Tests that duplication and closing has the right effect on Mach reference 264 // Tests that duplication and closing has the right effect on Mach reference
311 // counts. 265 // counts.
312 TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) { 266 TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) {
313 // Mach-based SharedMemory isn't support on OSX 10.6.
314 if (mac::IsOSSnowLeopard())
315 return;
316
317 mach_msg_type_number_t active_name_count = GetActiveNameCount(); 267 mach_msg_type_number_t active_name_count = GetActiveNameCount();
318 268
319 // Making a new SharedMemoryHandle increments the name count. 269 // Making a new SharedMemoryHandle increments the name count.
320 SharedMemoryHandle shm(s_memory_size); 270 SharedMemoryHandle shm(s_memory_size);
321 ASSERT_TRUE(shm.IsValid()); 271 ASSERT_TRUE(shm.IsValid());
322 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); 272 EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
323 273
324 // Duplicating the SharedMemoryHandle increments the ref count, but doesn't 274 // Duplicating the SharedMemoryHandle increments the ref count, but doesn't
325 // make a new name. 275 // make a new name.
326 shm.Duplicate(); 276 shm.Duplicate();
327 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); 277 EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
328 278
329 // Closing the SharedMemoryHandle decrements the ref count. The first time has 279 // Closing the SharedMemoryHandle decrements the ref count. The first time has
330 // no effect. 280 // no effect.
331 shm.Close(); 281 shm.Close();
332 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); 282 EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
333 283
334 // Closing the SharedMemoryHandle decrements the ref count. The second time 284 // Closing the SharedMemoryHandle decrements the ref count. The second time
335 // destroys the port. 285 // destroys the port.
336 shm.Close(); 286 shm.Close();
337 EXPECT_EQ(active_name_count, GetActiveNameCount()); 287 EXPECT_EQ(active_name_count, GetActiveNameCount());
338 } 288 }
339 289
340 // Tests that passing a SharedMemoryHandle to a SharedMemory object also passes 290 // Tests that passing a SharedMemoryHandle to a SharedMemory object also passes
341 // ownership, and that destroying the SharedMemory closes the SharedMemoryHandle 291 // ownership, and that destroying the SharedMemory closes the SharedMemoryHandle
342 // as well. 292 // as well.
343 TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) { 293 TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) {
344 // Mach-based SharedMemory isn't support on OSX 10.6.
345 if (mac::IsOSSnowLeopard())
346 return;
347
348 mach_msg_type_number_t active_name_count = GetActiveNameCount(); 294 mach_msg_type_number_t active_name_count = GetActiveNameCount();
349 295
350 // Making a new SharedMemoryHandle increments the name count. 296 // Making a new SharedMemoryHandle increments the name count.
351 SharedMemoryHandle shm(s_memory_size); 297 SharedMemoryHandle shm(s_memory_size);
352 ASSERT_TRUE(shm.IsValid()); 298 ASSERT_TRUE(shm.IsValid());
353 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); 299 EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
354 300
355 // Name count doesn't change when mapping the memory. 301 // Name count doesn't change when mapping the memory.
356 scoped_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); 302 scoped_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false));
357 shared_memory->Map(s_memory_size); 303 shared_memory->Map(s_memory_size);
358 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); 304 EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
359 305
360 // Destroying the SharedMemory object frees the resource. 306 // Destroying the SharedMemory object frees the resource.
361 shared_memory.reset(); 307 shared_memory.reset();
362 EXPECT_EQ(active_name_count, GetActiveNameCount()); 308 EXPECT_EQ(active_name_count, GetActiveNameCount());
363 } 309 }
364 310
365 // Tests that the read-only flag works. 311 // Tests that the read-only flag works.
366 TEST_F(SharedMemoryMacMultiProcessTest, MachReadOnly) { 312 TEST_F(SharedMemoryMacMultiProcessTest, MachReadOnly) {
367 // Mach-based SharedMemory isn't support on OSX 10.6. 313 SharedMemoryHandle shm(s_memory_size);
368 if (mac::IsOSSnowLeopard()) 314 ASSERT_TRUE(shm.IsValid());
369 return; 315 SharedMemory shared_memory(shm, false);
316 shared_memory.Map(s_memory_size);
317 memset(shared_memory.memory(), 'a', s_memory_size);
370 318
371 scoped_ptr<SharedMemory> shared_memory( 319 SharedMemoryHandle shm2 = shm.Duplicate();
372 CreateSharedMemory(s_memory_size).Pass());
373
374 SharedMemoryHandle shm2 = shared_memory->handle().Duplicate();
375 ASSERT_TRUE(shm2.IsValid()); 320 ASSERT_TRUE(shm2.IsValid());
376 SharedMemory shared_memory2(shm2, true); 321 SharedMemory shared_memory2(shm, true);
377 shared_memory2.Map(s_memory_size); 322 shared_memory2.Map(s_memory_size);
378 ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), ""); 323 ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
379 } 324 }
380 325
381 // Tests that the method ShareToProcess() works.
382 TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcess) {
383 // Mach-based SharedMemory isn't support on OSX 10.6.
384 if (mac::IsOSSnowLeopard())
385 return;
386
387 mach_msg_type_number_t active_name_count = GetActiveNameCount();
388
389 {
390 scoped_ptr<SharedMemory> shared_memory(
391 CreateSharedMemory(s_memory_size).Pass());
392
393 SharedMemoryHandle shm2;
394 ASSERT_TRUE(shared_memory->ShareToProcess(GetCurrentProcId(), &shm2));
395 ASSERT_TRUE(shm2.IsValid());
396 SharedMemory shared_memory2(shm2, true);
397 shared_memory2.Map(s_memory_size);
398
399 ASSERT_EQ(0, memcmp(shared_memory->memory(), shared_memory2.memory(),
400 s_memory_size));
401 }
402
403 EXPECT_EQ(active_name_count, GetActiveNameCount());
404 }
405
406 // Tests that the method ShareReadOnlyToProcess() creates a memory object that
407 // is read only.
408 TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonly) {
409 // Mach-based SharedMemory isn't support on OSX 10.6.
410 if (mac::IsOSSnowLeopard())
411 return;
412
413 scoped_ptr<SharedMemory> shared_memory(
414 CreateSharedMemory(s_memory_size).Pass());
415
416 // Check the protection levels.
417 int current_prot, max_prot;
418 ASSERT_TRUE(GetProtections(shared_memory->memory(),
419 shared_memory->mapped_size(), &current_prot,
420 &max_prot));
421 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot);
422 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot);
423
424 // Make a new memory object.
425 SharedMemoryHandle shm2;
426 ASSERT_TRUE(shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2));
427 ASSERT_TRUE(shm2.IsValid());
428
429 // Mapping with |readonly| set to |false| should fail.
430 SharedMemory shared_memory2(shm2, false);
431 shared_memory2.Map(s_memory_size);
432 ASSERT_EQ(nullptr, shared_memory2.memory());
433
434 // Now trying mapping with |readonly| set to |true|.
435 SharedMemory shared_memory3(shm2.Duplicate(), true);
436 shared_memory3.Map(s_memory_size);
437 ASSERT_NE(nullptr, shared_memory3.memory());
438
439 // Check the protection levels.
440 ASSERT_TRUE(GetProtections(shared_memory3.memory(),
441 shared_memory3.mapped_size(), &current_prot,
442 &max_prot));
443 ASSERT_EQ(VM_PROT_READ, current_prot);
444 ASSERT_EQ(VM_PROT_READ, max_prot);
445
446 // The memory should still be readonly, since the underlying memory object
447 // is readonly.
448 ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
449 }
450
451 // Tests that the method ShareReadOnlyToProcess() doesn't leak.
452 TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonlyLeak) {
453 // Mach-based SharedMemory isn't support on OSX 10.6.
454 if (mac::IsOSSnowLeopard())
455 return;
456
457 mach_msg_type_number_t active_name_count = GetActiveNameCount();
458
459 {
460 scoped_ptr<SharedMemory> shared_memory(
461 CreateSharedMemory(s_memory_size).Pass());
462
463 SharedMemoryHandle shm2;
464 ASSERT_TRUE(
465 shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2));
466 ASSERT_TRUE(shm2.IsValid());
467
468 // Intentionally map with |readonly| set to |false|.
469 SharedMemory shared_memory2(shm2, false);
470 shared_memory2.Map(s_memory_size);
471 }
472
473 EXPECT_EQ(active_name_count, GetActiveNameCount());
474 }
475
476 } // namespace base 326 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/shared_memory_mac.cc ('k') | ipc/attachment_broker_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698