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 #include "base/basictypes.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/shared_memory.h" 8 #include "base/process/kill.h" 9 #include "base/rand_util.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/sys_info.h" 12 #include "base/test/multiprocess_test.h" 13 #include "base/threading/platform_thread.h" 14 #include "base/time/time.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/multiprocess_func_list.h" 17 18 #if defined(OS_MACOSX) 19 #include "base/mac/scoped_nsautorelease_pool.h" 20 #endif 21 22 #if defined(OS_POSIX) 23 #include <errno.h> 24 #include <fcntl.h> 25 #include <sys/mman.h> 26 #include <sys/stat.h> 27 #include <sys/types.h> 28 #include <unistd.h> 29 #endif 30 31 #if defined(OS_WIN) 32 #include "base/win/scoped_handle.h" 33 #endif 34 35 static const int kNumThreads = 5; 36 #if !defined(OS_IOS) // iOS does not allow multiple processes. 37 static const int kNumTasks = 5; 38 #endif 39 40 namespace base { 41 42 namespace { 43 44 // Each thread will open the shared memory. Each thread will take a different 4 45 // byte int pointer, and keep changing it, with some small pauses in between. 46 // Verify that each thread's value in the shared memory is always correct. 47 class MultipleThreadMain : public PlatformThread::Delegate { 48 public: 49 explicit MultipleThreadMain(int16 id) : id_(id) {} 50 virtual ~MultipleThreadMain() {} 51 52 static void CleanUp() { 53 SharedMemory memory; 54 memory.Delete(s_test_name_); 55 } 56 57 // PlatformThread::Delegate interface. 58 virtual void ThreadMain() OVERRIDE { 59 #if defined(OS_MACOSX) 60 mac::ScopedNSAutoreleasePool pool; 61 #endif 62 const uint32 kDataSize = 1024; 63 SharedMemory memory; 64 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); 65 EXPECT_TRUE(rv); 66 rv = memory.Map(kDataSize); 67 EXPECT_TRUE(rv); 68 int *ptr = static_cast<int*>(memory.memory()) + id_; 69 EXPECT_EQ(0, *ptr); 70 71 for (int idx = 0; idx < 100; idx++) { 72 *ptr = idx; 73 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 74 EXPECT_EQ(*ptr, idx); 75 } 76 // Reset back to 0 for the next test that uses the same name. 77 *ptr = 0; 78 79 memory.Close(); 80 } 81 82 private: 83 int16 id_; 84 85 static const char* const s_test_name_; 86 87 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); 88 }; 89 90 const char* const MultipleThreadMain::s_test_name_ = 91 "SharedMemoryOpenThreadTest"; 92 93 // TODO(port): 94 // This test requires the ability to pass file descriptors between processes. 95 // We haven't done that yet in Chrome for POSIX. 96 #if defined(OS_WIN) 97 // Each thread will open the shared memory. Each thread will take the memory, 98 // and keep changing it while trying to lock it, with some small pauses in 99 // between. Verify that each thread's value in the shared memory is always 100 // correct. 101 class MultipleLockThread : public PlatformThread::Delegate { 102 public: 103 explicit MultipleLockThread(int id) : id_(id) {} 104 virtual ~MultipleLockThread() {} 105 106 // PlatformThread::Delegate interface. 107 virtual void ThreadMain() OVERRIDE { 108 const uint32 kDataSize = sizeof(int); 109 SharedMemoryHandle handle = NULL; 110 { 111 SharedMemory memory1; 112 EXPECT_TRUE(memory1.CreateNamedDeprecated( 113 "SharedMemoryMultipleLockThreadTest", true, kDataSize)); 114 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); 115 // TODO(paulg): Implement this once we have a posix version of 116 // SharedMemory::ShareToProcess. 117 EXPECT_TRUE(true); 118 } 119 120 SharedMemory memory2(handle, false); 121 EXPECT_TRUE(memory2.Map(kDataSize)); 122 volatile int* const ptr = static_cast<int*>(memory2.memory()); 123 124 for (int idx = 0; idx < 20; idx++) { 125 memory2.LockDeprecated(); 126 int i = (id_ << 16) + idx; 127 *ptr = i; 128 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 129 EXPECT_EQ(*ptr, i); 130 memory2.UnlockDeprecated(); 131 } 132 133 memory2.Close(); 134 } 135 136 private: 137 int id_; 138 139 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); 140 }; 141 #endif 142 143 } // namespace 144 145 // Android doesn't support SharedMemory::Open/Delete/ 146 // CreateNamedDeprecated(openExisting=true) 147 #if !defined(OS_ANDROID) 148 TEST(SharedMemoryTest, OpenClose) { 149 const uint32 kDataSize = 1024; 150 std::string test_name = "SharedMemoryOpenCloseTest"; 151 152 // Open two handles to a memory segment, confirm that they are mapped 153 // separately yet point to the same space. 154 SharedMemory memory1; 155 bool rv = memory1.Delete(test_name); 156 EXPECT_TRUE(rv); 157 rv = memory1.Delete(test_name); 158 EXPECT_TRUE(rv); 159 rv = memory1.Open(test_name, false); 160 EXPECT_FALSE(rv); 161 rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 162 EXPECT_TRUE(rv); 163 rv = memory1.Map(kDataSize); 164 EXPECT_TRUE(rv); 165 SharedMemory memory2; 166 rv = memory2.Open(test_name, false); 167 EXPECT_TRUE(rv); 168 rv = memory2.Map(kDataSize); 169 EXPECT_TRUE(rv); 170 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. 171 172 // Make sure we don't segfault. (it actually happened!) 173 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); 174 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); 175 176 // Write data to the first memory segment, verify contents of second. 177 memset(memory1.memory(), '1', kDataSize); 178 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); 179 180 // Close the first memory segment, and verify the second has the right data. 181 memory1.Close(); 182 char *start_ptr = static_cast<char *>(memory2.memory()); 183 char *end_ptr = start_ptr + kDataSize; 184 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) 185 EXPECT_EQ(*ptr, '1'); 186 187 // Close the second memory segment. 188 memory2.Close(); 189 190 rv = memory1.Delete(test_name); 191 EXPECT_TRUE(rv); 192 rv = memory2.Delete(test_name); 193 EXPECT_TRUE(rv); 194 } 195 196 TEST(SharedMemoryTest, OpenExclusive) { 197 const uint32 kDataSize = 1024; 198 const uint32 kDataSize2 = 2048; 199 std::ostringstream test_name_stream; 200 test_name_stream << "SharedMemoryOpenExclusiveTest." 201 << Time::Now().ToDoubleT(); 202 std::string test_name = test_name_stream.str(); 203 204 // Open two handles to a memory segment and check that 205 // open_existing_deprecated works as expected. 206 SharedMemory memory1; 207 bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 208 EXPECT_TRUE(rv); 209 210 // Memory1 knows it's size because it created it. 211 EXPECT_EQ(memory1.requested_size(), kDataSize); 212 213 rv = memory1.Map(kDataSize); 214 EXPECT_TRUE(rv); 215 216 // The mapped memory1 must be at least the size we asked for. 217 EXPECT_GE(memory1.mapped_size(), kDataSize); 218 219 // The mapped memory1 shouldn't exceed rounding for allocation granularity. 220 EXPECT_LT(memory1.mapped_size(), 221 kDataSize + base::SysInfo::VMAllocationGranularity()); 222 223 memset(memory1.memory(), 'G', kDataSize); 224 225 SharedMemory memory2; 226 // Should not be able to create if openExisting is false. 227 rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); 228 EXPECT_FALSE(rv); 229 230 // Should be able to create with openExisting true. 231 rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); 232 EXPECT_TRUE(rv); 233 234 // Memory2 shouldn't know the size because we didn't create it. 235 EXPECT_EQ(memory2.requested_size(), 0U); 236 237 // We should be able to map the original size. 238 rv = memory2.Map(kDataSize); 239 EXPECT_TRUE(rv); 240 241 // The mapped memory2 must be at least the size of the original. 242 EXPECT_GE(memory2.mapped_size(), kDataSize); 243 244 // The mapped memory2 shouldn't exceed rounding for allocation granularity. 245 EXPECT_LT(memory2.mapped_size(), 246 kDataSize2 + base::SysInfo::VMAllocationGranularity()); 247 248 // Verify that opening memory2 didn't truncate or delete memory 1. 249 char *start_ptr = static_cast<char *>(memory2.memory()); 250 char *end_ptr = start_ptr + kDataSize; 251 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { 252 EXPECT_EQ(*ptr, 'G'); 253 } 254 255 memory1.Close(); 256 memory2.Close(); 257 258 rv = memory1.Delete(test_name); 259 EXPECT_TRUE(rv); 260 } 261 #endif 262 263 // Create a set of N threads to each open a shared memory segment and write to 264 // it. Verify that they are always reading/writing consistent data. 265 TEST(SharedMemoryTest, MultipleThreads) { 266 MultipleThreadMain::CleanUp(); 267 // On POSIX we have a problem when 2 threads try to create the shmem 268 // (a file) at exactly the same time, since create both creates the 269 // file and zerofills it. We solve the problem for this unit test 270 // (make it not flaky) by starting with 1 thread, then 271 // intentionally don't clean up its shmem before running with 272 // kNumThreads. 273 274 int threadcounts[] = { 1, kNumThreads }; 275 for (size_t i = 0; i < arraysize(threadcounts); i++) { 276 int numthreads = threadcounts[i]; 277 scoped_ptr<PlatformThreadHandle[]> thread_handles; 278 scoped_ptr<MultipleThreadMain*[]> thread_delegates; 279 280 thread_handles.reset(new PlatformThreadHandle[numthreads]); 281 thread_delegates.reset(new MultipleThreadMain*[numthreads]); 282 283 // Spawn the threads. 284 for (int16 index = 0; index < numthreads; index++) { 285 PlatformThreadHandle pth; 286 thread_delegates[index] = new MultipleThreadMain(index); 287 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 288 thread_handles[index] = pth; 289 } 290 291 // Wait for the threads to finish. 292 for (int index = 0; index < numthreads; index++) { 293 PlatformThread::Join(thread_handles[index]); 294 delete thread_delegates[index]; 295 } 296 } 297 MultipleThreadMain::CleanUp(); 298 } 299 300 // TODO(port): this test requires the MultipleLockThread class 301 // (defined above), which requires the ability to pass file 302 // descriptors between processes. We haven't done that yet in Chrome 303 // for POSIX. 304 #if defined(OS_WIN) 305 // Create a set of threads to each open a shared memory segment and write to it 306 // with the lock held. Verify that they are always reading/writing consistent 307 // data. 308 TEST(SharedMemoryTest, Lock) { 309 PlatformThreadHandle thread_handles[kNumThreads]; 310 MultipleLockThread* thread_delegates[kNumThreads]; 311 312 // Spawn the threads. 313 for (int index = 0; index < kNumThreads; ++index) { 314 PlatformThreadHandle pth; 315 thread_delegates[index] = new MultipleLockThread(index); 316 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 317 thread_handles[index] = pth; 318 } 319 320 // Wait for the threads to finish. 321 for (int index = 0; index < kNumThreads; ++index) { 322 PlatformThread::Join(thread_handles[index]); 323 delete thread_delegates[index]; 324 } 325 } 326 #endif 327 328 // Allocate private (unique) shared memory with an empty string for a 329 // name. Make sure several of them don't point to the same thing as 330 // we might expect if the names are equal. 331 TEST(SharedMemoryTest, AnonymousPrivate) { 332 int i, j; 333 int count = 4; 334 bool rv; 335 const uint32 kDataSize = 8192; 336 337 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); 338 scoped_ptr<int*[]> pointers(new int*[count]); 339 ASSERT_TRUE(memories.get()); 340 ASSERT_TRUE(pointers.get()); 341 342 for (i = 0; i < count; i++) { 343 rv = memories[i].CreateAndMapAnonymous(kDataSize); 344 EXPECT_TRUE(rv); 345 int *ptr = static_cast<int*>(memories[i].memory()); 346 EXPECT_TRUE(ptr); 347 pointers[i] = ptr; 348 } 349 350 for (i = 0; i < count; i++) { 351 // zero out the first int in each except for i; for that one, make it 100. 352 for (j = 0; j < count; j++) { 353 if (i == j) 354 pointers[j][0] = 100; 355 else 356 pointers[j][0] = 0; 357 } 358 // make sure there is no bleeding of the 100 into the other pointers 359 for (j = 0; j < count; j++) { 360 if (i == j) 361 EXPECT_EQ(100, pointers[j][0]); 362 else 363 EXPECT_EQ(0, pointers[j][0]); 364 } 365 } 366 367 for (int i = 0; i < count; i++) { 368 memories[i].Close(); 369 } 370 } 371 372 TEST(SharedMemoryTest, ShareReadOnly) { 373 StringPiece contents = "Hello World"; 374 375 SharedMemory writable_shmem; 376 SharedMemoryCreateOptions options; 377 options.size = contents.size(); 378 options.share_read_only = true; 379 ASSERT_TRUE(writable_shmem.Create(options)); 380 ASSERT_TRUE(writable_shmem.Map(options.size)); 381 memcpy(writable_shmem.memory(), contents.data(), contents.size()); 382 EXPECT_TRUE(writable_shmem.Unmap()); 383 384 SharedMemoryHandle readonly_handle; 385 ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(), 386 &readonly_handle)); 387 SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true); 388 389 ASSERT_TRUE(readonly_shmem.Map(contents.size())); 390 EXPECT_EQ(contents, 391 StringPiece(static_cast<const char*>(readonly_shmem.memory()), 392 contents.size())); 393 EXPECT_TRUE(readonly_shmem.Unmap()); 394 395 // Make sure the writable instance is still writable. 396 ASSERT_TRUE(writable_shmem.Map(contents.size())); 397 StringPiece new_contents = "Goodbye"; 398 memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size()); 399 EXPECT_EQ(new_contents, 400 StringPiece(static_cast<const char*>(writable_shmem.memory()), 401 new_contents.size())); 402 403 // We'd like to check that if we send the read-only segment to another 404 // process, then that other process can't reopen it read/write. (Since that 405 // would be a security hole.) Setting up multiple processes is hard in a 406 // unittest, so this test checks that the *current* process can't reopen the 407 // segment read/write. I think the test here is stronger than we actually 408 // care about, but there's a remote possibility that sending a file over a 409 // pipe would transform it into read/write. 410 SharedMemoryHandle handle = readonly_shmem.handle(); 411 412 #if defined(OS_ANDROID) 413 // The "read-only" handle is still writable on Android: 414 // http://crbug.com/320865 415 (void)handle; 416 #elif defined(OS_POSIX) 417 EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE) 418 << "The descriptor itself should be read-only."; 419 420 errno = 0; 421 void* writable = mmap( 422 NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0); 423 int mmap_errno = errno; 424 EXPECT_EQ(MAP_FAILED, writable) 425 << "It shouldn't be possible to re-mmap the descriptor writable."; 426 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); 427 if (writable != MAP_FAILED) 428 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); 429 430 #elif defined(OS_WIN) 431 EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0)) 432 << "Shouldn't be able to map memory writable."; 433 434 HANDLE temp_handle; 435 BOOL rv = ::DuplicateHandle(GetCurrentProcess(), 436 handle, 437 GetCurrentProcess(), 438 &temp_handle, 439 FILE_MAP_ALL_ACCESS, 440 false, 441 0); 442 EXPECT_EQ(FALSE, rv) 443 << "Shouldn't be able to duplicate the handle into a writable one."; 444 if (rv) 445 base::win::ScopedHandle writable_handle(temp_handle); 446 rv = ::DuplicateHandle(GetCurrentProcess(), 447 handle, 448 GetCurrentProcess(), 449 &temp_handle, 450 FILE_MAP_READ, 451 false, 452 0); 453 EXPECT_EQ(TRUE, rv) 454 << "Should be able to duplicate the handle into a readable one."; 455 if (rv) 456 base::win::ScopedHandle writable_handle(temp_handle); 457 #else 458 #error Unexpected platform; write a test that tries to make 'handle' writable. 459 #endif // defined(OS_POSIX) || defined(OS_WIN) 460 } 461 462 TEST(SharedMemoryTest, ShareToSelf) { 463 StringPiece contents = "Hello World"; 464 465 SharedMemory shmem; 466 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); 467 memcpy(shmem.memory(), contents.data(), contents.size()); 468 EXPECT_TRUE(shmem.Unmap()); 469 470 SharedMemoryHandle shared_handle; 471 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 472 SharedMemory shared(shared_handle, /*readonly=*/false); 473 474 ASSERT_TRUE(shared.Map(contents.size())); 475 EXPECT_EQ( 476 contents, 477 StringPiece(static_cast<const char*>(shared.memory()), contents.size())); 478 479 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 480 SharedMemory readonly(shared_handle, /*readonly=*/true); 481 482 ASSERT_TRUE(readonly.Map(contents.size())); 483 EXPECT_EQ(contents, 484 StringPiece(static_cast<const char*>(readonly.memory()), 485 contents.size())); 486 } 487 488 TEST(SharedMemoryTest, MapAt) { 489 ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32)); 490 const size_t kCount = SysInfo::VMAllocationGranularity(); 491 const size_t kDataSize = kCount * sizeof(uint32); 492 493 SharedMemory memory; 494 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 495 uint32* ptr = static_cast<uint32*>(memory.memory()); 496 ASSERT_NE(ptr, static_cast<void*>(NULL)); 497 498 for (size_t i = 0; i < kCount; ++i) { 499 ptr[i] = i; 500 } 501 502 memory.Unmap(); 503 504 off_t offset = SysInfo::VMAllocationGranularity(); 505 ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset)); 506 offset /= sizeof(uint32); 507 ptr = static_cast<uint32*>(memory.memory()); 508 ASSERT_NE(ptr, static_cast<void*>(NULL)); 509 for (size_t i = offset; i < kCount; ++i) { 510 EXPECT_EQ(ptr[i - offset], i); 511 } 512 } 513 514 TEST(SharedMemoryTest, MapTwice) { 515 const uint32 kDataSize = 1024; 516 SharedMemory memory; 517 bool rv = memory.CreateAndMapAnonymous(kDataSize); 518 EXPECT_TRUE(rv); 519 520 void* old_address = memory.memory(); 521 522 rv = memory.Map(kDataSize); 523 EXPECT_FALSE(rv); 524 EXPECT_EQ(old_address, memory.memory()); 525 } 526 527 #if defined(OS_POSIX) 528 // This test is not applicable for iOS (crbug.com/399384). 529 #if !defined(OS_IOS) 530 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC. 531 TEST(SharedMemoryTest, AnonymousExecutable) { 532 const uint32 kTestSize = 1 << 16; 533 534 SharedMemory shared_memory; 535 SharedMemoryCreateOptions options; 536 options.size = kTestSize; 537 options.executable = true; 538 539 EXPECT_TRUE(shared_memory.Create(options)); 540 EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size())); 541 542 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(), 543 PROT_READ | PROT_EXEC)); 544 } 545 #endif // !defined(OS_IOS) 546 547 // Android supports a different permission model than POSIX for its "ashmem" 548 // shared memory implementation. So the tests about file permissions are not 549 // included on Android. 550 #if !defined(OS_ANDROID) 551 552 // Set a umask and restore the old mask on destruction. 553 class ScopedUmaskSetter { 554 public: 555 explicit ScopedUmaskSetter(mode_t target_mask) { 556 old_umask_ = umask(target_mask); 557 } 558 ~ScopedUmaskSetter() { umask(old_umask_); } 559 private: 560 mode_t old_umask_; 561 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 562 }; 563 564 // Create a shared memory object, check its permissions. 565 TEST(SharedMemoryTest, FilePermissionsAnonymous) { 566 const uint32 kTestSize = 1 << 8; 567 568 SharedMemory shared_memory; 569 SharedMemoryCreateOptions options; 570 options.size = kTestSize; 571 // Set a file mode creation mask that gives all permissions. 572 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 573 574 EXPECT_TRUE(shared_memory.Create(options)); 575 576 int shm_fd = shared_memory.handle().fd; 577 struct stat shm_stat; 578 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); 579 // Neither the group, nor others should be able to read the shared memory 580 // file. 581 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 582 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 583 } 584 585 // Create a shared memory object, check its permissions. 586 TEST(SharedMemoryTest, FilePermissionsNamed) { 587 const uint32 kTestSize = 1 << 8; 588 589 SharedMemory shared_memory; 590 SharedMemoryCreateOptions options; 591 options.size = kTestSize; 592 std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) + 593 "-" + Uint64ToString(RandUint64()); 594 options.name_deprecated = &shared_mem_name; 595 // Set a file mode creation mask that gives all permissions. 596 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 597 598 EXPECT_TRUE(shared_memory.Create(options)); 599 // Clean-up the backing file name immediately, we don't need it. 600 EXPECT_TRUE(shared_memory.Delete(shared_mem_name)); 601 602 int shm_fd = shared_memory.handle().fd; 603 struct stat shm_stat; 604 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); 605 // Neither the group, nor others should have been able to open the shared 606 // memory file while its name existed. 607 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 608 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 609 } 610 #endif // !defined(OS_ANDROID) 611 612 #endif // defined(OS_POSIX) 613 614 // Map() will return addresses which are aligned to the platform page size, this 615 // varies from platform to platform though. Since we'd like to advertise a 616 // minimum alignment that callers can count on, test for it here. 617 TEST(SharedMemoryTest, MapMinimumAlignment) { 618 static const int kDataSize = 8192; 619 620 SharedMemory shared_memory; 621 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); 622 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( 623 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 624 shared_memory.Close(); 625 } 626 627 #if !defined(OS_IOS) // iOS does not allow multiple processes. 628 629 // On POSIX it is especially important we test shmem across processes, 630 // not just across threads. But the test is enabled on all platforms. 631 class SharedMemoryProcessTest : public MultiProcessTest { 632 public: 633 634 static void CleanUp() { 635 SharedMemory memory; 636 memory.Delete(s_test_name_); 637 } 638 639 static int TaskTestMain() { 640 int errors = 0; 641 #if defined(OS_MACOSX) 642 mac::ScopedNSAutoreleasePool pool; 643 #endif 644 const uint32 kDataSize = 1024; 645 SharedMemory memory; 646 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); 647 EXPECT_TRUE(rv); 648 if (rv != true) 649 errors++; 650 rv = memory.Map(kDataSize); 651 EXPECT_TRUE(rv); 652 if (rv != true) 653 errors++; 654 int *ptr = static_cast<int*>(memory.memory()); 655 656 for (int idx = 0; idx < 20; idx++) { 657 memory.LockDeprecated(); 658 int i = (1 << 16) + idx; 659 *ptr = i; 660 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10)); 661 if (*ptr != i) 662 errors++; 663 memory.UnlockDeprecated(); 664 } 665 666 memory.Close(); 667 return errors; 668 } 669 670 private: 671 static const char* const s_test_name_; 672 }; 673 674 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; 675 676 TEST_F(SharedMemoryProcessTest, Tasks) { 677 SharedMemoryProcessTest::CleanUp(); 678 679 ProcessHandle handles[kNumTasks]; 680 for (int index = 0; index < kNumTasks; ++index) { 681 handles[index] = SpawnChild("SharedMemoryTestMain"); 682 ASSERT_TRUE(handles[index]); 683 } 684 685 int exit_code = 0; 686 for (int index = 0; index < kNumTasks; ++index) { 687 EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code)); 688 EXPECT_EQ(0, exit_code); 689 } 690 691 SharedMemoryProcessTest::CleanUp(); 692 } 693 694 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { 695 return SharedMemoryProcessTest::TaskTestMain(); 696 } 697 698 #endif // !OS_IOS 699 700 } // namespace base 701