145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Copyright (c) 2012 The Chromium Authors. All rights reserved. 245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be 345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// found in the LICENSE file. 445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/memory/shared_memory.h" 694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <stddef.h> 845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <stdint.h> 945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 1094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 1245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/atomicops.h" 1345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/macros.h" 1445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/memory/shared_memory_handle.h" 1545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/process/kill.h" 1645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/rand_util.h" 1745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/strings/string_number_conversions.h" 1845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/sys_info.h" 1945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/test/multiprocess_test.h" 2045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/threading/platform_thread.h" 2145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/time/time.h" 2245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "build/build_config.h" 2345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "testing/gtest/include/gtest/gtest.h" 2445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "testing/multiprocess_func_list.h" 2545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 2645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_POSIX) 2745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <errno.h> 2845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <fcntl.h> 2945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/mman.h> 3045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/stat.h> 3145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/types.h> 3245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <unistd.h> 3345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif 3445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 3545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN) 3645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/win/scoped_handle.h" 3745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif 3845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 3945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkonamespace base { 4045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 4145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkonamespace { 4245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 4345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_MACOSX) 4445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Each thread will open the shared memory. Each thread will take a different 4 4545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// byte int pointer, and keep changing it, with some small pauses in between. 4645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Verify that each thread's value in the shared memory is always correct. 4745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass MultipleThreadMain : public PlatformThread::Delegate { 4845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public: 4945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko explicit MultipleThreadMain(int16_t id) : id_(id) {} 5045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ~MultipleThreadMain() override {} 5145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 5245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static void CleanUp() { 5345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 5445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Delete(s_test_name_); 5545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 5645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 5745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // PlatformThread::Delegate interface. 5845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko void ThreadMain() override { 5945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize = 1024; 6045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 6145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); 6245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 6345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory.Map(kDataSize); 6445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 6545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int* ptr = static_cast<int*>(memory.memory()) + id_; 6645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, *ptr); 6745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 6845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int idx = 0; idx < 100; idx++) { 6945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko *ptr = idx; 7045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 7145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(*ptr, idx); 7245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 7345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Reset back to 0 for the next test that uses the same name. 7445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko *ptr = 0; 7545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 7645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Close(); 7745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 7845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 7945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko private: 8045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int16_t id_; 8145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 8245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static const char s_test_name_[]; 8345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 8445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); 8545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}; 8645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 8745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst char MultipleThreadMain::s_test_name_[] = 8845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko "SharedMemoryOpenThreadTest"; 8945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // !defined(OS_MACOSX) 9045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 9145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} // namespace 9245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 9345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android/Mac doesn't support SharedMemory::Open/Delete/ 9445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// CreateNamedDeprecated(openExisting=true) 9545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_ANDROID) && !defined(OS_MACOSX) 9645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, OpenClose) { 9745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize = 1024; 9845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::string test_name = "SharedMemoryOpenCloseTest"; 9945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 10045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Open two handles to a memory segment, confirm that they are mapped 10145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // separately yet point to the same space. 10245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory1; 10345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory1.Delete(test_name); 10445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 10545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Delete(test_name); 10645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 10745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Open(test_name, false); 10845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(rv); 10945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 11045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 11145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Map(kDataSize); 11245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 11345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory2; 11445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.Open(test_name, false); 11545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 11645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.Map(kDataSize); 11745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 11845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. 11945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 12045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Make sure we don't segfault. (it actually happened!) 12145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); 12245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); 12345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 12445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Write data to the first memory segment, verify contents of second. 12545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memset(memory1.memory(), '1', kDataSize); 12645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); 12745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 12845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Close the first memory segment, and verify the second has the right data. 12945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory1.Close(); 13045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko char* start_ptr = static_cast<char*>(memory2.memory()); 13145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko char* end_ptr = start_ptr + kDataSize; 13245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (char* ptr = start_ptr; ptr < end_ptr; ptr++) 13345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(*ptr, '1'); 13445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 13545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Close the second memory segment. 13645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory2.Close(); 13745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 13845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Delete(test_name); 13945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 14045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.Delete(test_name); 14145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 14245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 14345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 14445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, OpenExclusive) { 14545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize = 1024; 14645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize2 = 2048; 14745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::ostringstream test_name_stream; 14845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko test_name_stream << "SharedMemoryOpenExclusiveTest." 14945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << Time::Now().ToDoubleT(); 15045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::string test_name = test_name_stream.str(); 15145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 15245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Open two handles to a memory segment and check that 15345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // open_existing_deprecated works as expected. 15445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory1; 15545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 15645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 15745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 15845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Memory1 knows it's size because it created it. 15945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(memory1.requested_size(), kDataSize); 16045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 16145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Map(kDataSize); 16245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 16345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 16445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // The mapped memory1 must be at least the size we asked for. 16545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_GE(memory1.mapped_size(), kDataSize); 16645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 16745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // The mapped memory1 shouldn't exceed rounding for allocation granularity. 16845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_LT(memory1.mapped_size(), 16945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko kDataSize + SysInfo::VMAllocationGranularity()); 17045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 17145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memset(memory1.memory(), 'G', kDataSize); 17245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 17345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory2; 17445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Should not be able to create if openExisting is false. 17545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); 17645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(rv); 17745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 17845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Should be able to create with openExisting true. 17945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); 18045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 18145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 18245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Memory2 shouldn't know the size because we didn't create it. 18345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(memory2.requested_size(), 0U); 18445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 18545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // We should be able to map the original size. 18645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory2.Map(kDataSize); 18745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 18845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 18945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // The mapped memory2 must be at least the size of the original. 19045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_GE(memory2.mapped_size(), kDataSize); 19145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 19245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // The mapped memory2 shouldn't exceed rounding for allocation granularity. 19345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_LT(memory2.mapped_size(), 19445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko kDataSize2 + SysInfo::VMAllocationGranularity()); 19545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 19645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Verify that opening memory2 didn't truncate or delete memory 1. 19745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko char* start_ptr = static_cast<char*>(memory2.memory()); 19845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko char* end_ptr = start_ptr + kDataSize; 19945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { 20045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(*ptr, 'G'); 20145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 20245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 20345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory1.Close(); 20445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory2.Close(); 20545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 20645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory1.Delete(test_name); 20745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 20845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 20945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) 21045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 21145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Check that memory is still mapped after its closed. 21245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, CloseNoUnmap) { 21345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const size_t kDataSize = 4096; 21445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 21545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 21645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 21745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko char* ptr = static_cast<char*>(memory.memory()); 21845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_NE(ptr, static_cast<void*>(NULL)); 21945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memset(ptr, 'G', kDataSize); 22045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 22145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Close(); 22245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 22345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(ptr, memory.memory()); 22445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); 22545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 22645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (size_t i = 0; i < kDataSize; i++) { 22745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ('G', ptr[i]); 22845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 22945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 23045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Unmap(); 23145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(nullptr, memory.memory()); 23245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 23345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 23445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_MACOSX) 23545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a set of N threads to each open a shared memory segment and write to 23645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// it. Verify that they are always reading/writing consistent data. 23745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MultipleThreads) { 23845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const int kNumThreads = 5; 23945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 24045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko MultipleThreadMain::CleanUp(); 24145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // On POSIX we have a problem when 2 threads try to create the shmem 24245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // (a file) at exactly the same time, since create both creates the 24345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // file and zerofills it. We solve the problem for this unit test 24445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // (make it not flaky) by starting with 1 thread, then 24545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // intentionally don't clean up its shmem before running with 24645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // kNumThreads. 24745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 24845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int threadcounts[] = { 1, kNumThreads }; 24945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (size_t i = 0; i < arraysize(threadcounts); i++) { 25045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int numthreads = threadcounts[i]; 25194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<PlatformThreadHandle[]> thread_handles; 25294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<MultipleThreadMain* []> thread_delegates; 25345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 25445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko thread_handles.reset(new PlatformThreadHandle[numthreads]); 25545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko thread_delegates.reset(new MultipleThreadMain*[numthreads]); 25645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 25745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Spawn the threads. 25845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int16_t index = 0; index < numthreads; index++) { 25945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PlatformThreadHandle pth; 26045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko thread_delegates[index] = new MultipleThreadMain(index); 26145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 26245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko thread_handles[index] = pth; 26345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 26445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 26545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Wait for the threads to finish. 26645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int index = 0; index < numthreads; index++) { 26745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PlatformThread::Join(thread_handles[index]); 26845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko delete thread_delegates[index]; 26945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 27045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 27145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko MultipleThreadMain::CleanUp(); 27245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 27345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif 27445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 27545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Allocate private (unique) shared memory with an empty string for a 27645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// name. Make sure several of them don't point to the same thing as 27745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// we might expect if the names are equal. 27845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, AnonymousPrivate) { 27945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int i, j; 28045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int count = 4; 28145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv; 28245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize = 8192; 28345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 28494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]); 28594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<int* []> pointers(new int*[count]); 28645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(memories.get()); 28745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(pointers.get()); 28845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 28945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (i = 0; i < count; i++) { 29045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memories[i].CreateAndMapAnonymous(kDataSize); 29145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 29245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int* ptr = static_cast<int*>(memories[i].memory()); 29345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(ptr); 29445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko pointers[i] = ptr; 29545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 29645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 29745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (i = 0; i < count; i++) { 29845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // zero out the first int in each except for i; for that one, make it 100. 29945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (j = 0; j < count; j++) { 30045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (i == j) 30145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko pointers[j][0] = 100; 30245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko else 30345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko pointers[j][0] = 0; 30445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 30545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // make sure there is no bleeding of the 100 into the other pointers 30645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (j = 0; j < count; j++) { 30745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (i == j) 30845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(100, pointers[j][0]); 30945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko else 31045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, pointers[j][0]); 31145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 31245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 31345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 31445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int i = 0; i < count; i++) { 31545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memories[i].Close(); 31645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 31745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 31845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 31945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, ShareReadOnly) { 32045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece contents = "Hello World"; 32145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 32245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory writable_shmem; 32345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryCreateOptions options; 32445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.size = contents.size(); 32545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.share_read_only = true; 32636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS) 32736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The Mach functionality is tested in shared_memory_mac_unittest.cc. 32836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe options.type = SharedMemoryHandle::POSIX; 32936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 33045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(writable_shmem.Create(options)); 33145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(writable_shmem.Map(options.size)); 33245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memcpy(writable_shmem.memory(), contents.data(), contents.size()); 33345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(writable_shmem.Unmap()); 33445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 33545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryHandle readonly_handle; 33645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(), 33745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko &readonly_handle)); 33845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true); 33945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 34045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(readonly_shmem.Map(contents.size())); 34145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(contents, 34245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece(static_cast<const char*>(readonly_shmem.memory()), 34345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko contents.size())); 34445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(readonly_shmem.Unmap()); 34545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 34645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Make sure the writable instance is still writable. 34745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(writable_shmem.Map(contents.size())); 34845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece new_contents = "Goodbye"; 34945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size()); 35045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(new_contents, 35145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece(static_cast<const char*>(writable_shmem.memory()), 35245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko new_contents.size())); 35345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 35445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // We'd like to check that if we send the read-only segment to another 35545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // process, then that other process can't reopen it read/write. (Since that 35645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // would be a security hole.) Setting up multiple processes is hard in a 35745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // unittest, so this test checks that the *current* process can't reopen the 35845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // segment read/write. I think the test here is stronger than we actually 35945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // care about, but there's a remote possibility that sending a file over a 36045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // pipe would transform it into read/write. 36145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryHandle handle = readonly_shmem.handle(); 36245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 36345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_ANDROID) 36445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // The "read-only" handle is still writable on Android: 36545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // http://crbug.com/320865 36645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko (void)handle; 36745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#elif defined(OS_POSIX) 36845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle); 36945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE) 37045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "The descriptor itself should be read-only."; 37145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 37245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko errno = 0; 37345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE, 37445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko MAP_SHARED, handle_fd, 0); 37545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int mmap_errno = errno; 37645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(MAP_FAILED, writable) 37745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "It shouldn't be possible to re-mmap the descriptor writable."; 37845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); 37945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (writable != MAP_FAILED) 38045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); 38145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 38245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#elif defined(OS_WIN) 38345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0)) 38445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "Shouldn't be able to map memory writable."; 38545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 38645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko HANDLE temp_handle; 38745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 38845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko GetCurrentProcess(), &temp_handle, 38945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko FILE_MAP_ALL_ACCESS, false, 0); 39045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(FALSE, rv) 39145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "Shouldn't be able to duplicate the handle into a writable one."; 39245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (rv) 39345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko win::ScopedHandle writable_handle(temp_handle); 39445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 39545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko GetCurrentProcess(), &temp_handle, FILE_MAP_READ, 39645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko false, 0); 39745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(TRUE, rv) 39845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko << "Should be able to duplicate the handle into a readable one."; 39945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (rv) 40045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko win::ScopedHandle writable_handle(temp_handle); 40145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#else 40245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#error Unexpected platform; write a test that tries to make 'handle' writable. 40345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // defined(OS_POSIX) || defined(OS_WIN) 40445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 40545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 40645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, ShareToSelf) { 40745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece contents = "Hello World"; 40845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 40945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shmem; 41045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); 41145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memcpy(shmem.memory(), contents.data(), contents.size()); 41245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shmem.Unmap()); 41345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 41445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryHandle shared_handle; 41545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 41645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN) 41745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 41845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif 41945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared(shared_handle, /*readonly=*/false); 42045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 42145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shared.Map(contents.size())); 42245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ( 42345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko contents, 42445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece(static_cast<const char*>(shared.memory()), contents.size())); 42545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 42645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko shared_handle = SharedMemoryHandle(); 42745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 42845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN) 42945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 43045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif 43145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory readonly(shared_handle, /*readonly=*/true); 43245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 43345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(readonly.Map(contents.size())); 43445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(contents, 43545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StringPiece(static_cast<const char*>(readonly.memory()), 43645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko contents.size())); 43745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 43845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 43945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapAt) { 44045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t)); 44145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const size_t kCount = SysInfo::VMAllocationGranularity(); 44245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const size_t kDataSize = kCount * sizeof(uint32_t); 44345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 44445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 44545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 44645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko uint32_t* ptr = static_cast<uint32_t*>(memory.memory()); 44745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_NE(ptr, static_cast<void*>(NULL)); 44845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 44945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (size_t i = 0; i < kCount; ++i) { 45045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ptr[i] = i; 45145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 45245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 45345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Unmap(); 45445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 45545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko off_t offset = SysInfo::VMAllocationGranularity(); 45645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset)); 45745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko offset /= sizeof(uint32_t); 45845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ptr = static_cast<uint32_t*>(memory.memory()); 45945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_NE(ptr, static_cast<void*>(NULL)); 46045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (size_t i = offset; i < kCount; ++i) { 46145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(ptr[i - offset], i); 46245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 46345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 46445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 46545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapTwice) { 46645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kDataSize = 1024; 46745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 46845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory.CreateAndMapAnonymous(kDataSize); 46945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 47045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 47145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko void* old_address = memory.memory(); 47245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 47345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory.Map(kDataSize); 47445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(rv); 47545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(old_address, memory.memory()); 47645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 47745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 47836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_POSIX) 47945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// This test is not applicable for iOS (crbug.com/399384). 48045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_IOS) 48145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC. 48245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, AnonymousExecutable) { 48345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kTestSize = 1 << 16; 48445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 48545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory; 48645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryCreateOptions options; 48745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.size = kTestSize; 48845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.executable = true; 48936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS) 49036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The Mach functionality is tested in shared_memory_mac_unittest.cc. 49136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe options.type = SharedMemoryHandle::POSIX; 49236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 49345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 49445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory.Create(options)); 49545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size())); 49645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 49745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(), 49845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PROT_READ | PROT_EXEC)); 49945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 50045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // !defined(OS_IOS) 50145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 50245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android supports a different permission model than POSIX for its "ashmem" 50345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// shared memory implementation. So the tests about file permissions are not 50445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// included on Android. 50545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_ANDROID) 50645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 50745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Set a umask and restore the old mask on destruction. 50845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass ScopedUmaskSetter { 50945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public: 51045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko explicit ScopedUmaskSetter(mode_t target_mask) { 51145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko old_umask_ = umask(target_mask); 51245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 51345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ~ScopedUmaskSetter() { umask(old_umask_); } 51445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko private: 51545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko mode_t old_umask_; 51645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 51745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}; 51845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 51945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, check its permissions. 52045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, FilePermissionsAnonymous) { 52145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kTestSize = 1 << 8; 52245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 52345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory; 52445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryCreateOptions options; 52545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.size = kTestSize; 52636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS) 52736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The Mach functionality is tested in shared_memory_mac_unittest.cc. 52836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe options.type = SharedMemoryHandle::POSIX; 52936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 53045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Set a file mode creation mask that gives all permissions. 53145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 53245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 53345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory.Create(options)); 53445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 53545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int shm_fd = 53645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 53745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko struct stat shm_stat; 53845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); 53945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Neither the group, nor others should be able to read the shared memory 54045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // file. 54145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 54245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 54345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 54445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 54545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, check its permissions. 54645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, FilePermissionsNamed) { 54745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const uint32_t kTestSize = 1 << 8; 54845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 54945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory; 55045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryCreateOptions options; 55145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.size = kTestSize; 55236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS) 55336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The Mach functionality is tested in shared_memory_mac_unittest.cc. 55436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe options.type = SharedMemoryHandle::POSIX; 55536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 55645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 55745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Set a file mode creation mask that gives all permissions. 55845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 55945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 56045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory.Create(options)); 56145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 56245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 56345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko struct stat shm_stat; 56445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, fstat(fd, &shm_stat)); 56545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Neither the group, nor others should have been able to open the shared 56645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // memory file while its name existed. 56745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 56845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 56945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 57045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // !defined(OS_ANDROID) 57145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 57236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif // defined(OS_POSIX) 57345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 57445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Map() will return addresses which are aligned to the platform page size, this 57545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// varies from platform to platform though. Since we'd like to advertise a 57645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// minimum alignment that callers can count on, test for it here. 57745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapMinimumAlignment) { 57845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static const int kDataSize = 8192; 57945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 58045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory; 58145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); 58245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( 58345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 58445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko shared_memory.Close(); 58545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 58645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 58745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN) 58845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, UnsafeImageSection) { 58945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const char kTestSectionName[] = "UnsafeImageSection"; 59045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko wchar_t path[MAX_PATH]; 59145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U); 59245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 59345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Map the current executable image to save us creating a new PE file on disk. 59494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez base::win::ScopedHandle file_handle(::CreateFile( 59594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); 59645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(file_handle.IsValid()); 59745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko base::win::ScopedHandle section_handle( 59845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ::CreateFileMappingA(file_handle.Get(), nullptr, 59945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName)); 60045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(section_handle.IsValid()); 60145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 60245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Check direct opening by name, from handle and duplicated from handle. 60345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory_open; 60445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true)); 60545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shared_memory_open.Map(1)); 60645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(nullptr, shared_memory_open.memory()); 60745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 60845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory_handle_local( 60945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true); 61045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shared_memory_handle_local.Map(1)); 61145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(nullptr, shared_memory_handle_local.memory()); 61245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 61345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Check that a handle without SECTION_QUERY also can't be mapped as it can't 61445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // be checked. 61545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory_handle_dummy; 61645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryCreateOptions options; 61745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko options.size = 0x1000; 61845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(shared_memory_handle_dummy.Create(options)); 61945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko HANDLE handle_no_query; 62045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(::DuplicateHandle( 62145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(), 62245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0)); 62345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory shared_memory_handle_no_query( 62445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true); 62545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(shared_memory_handle_no_query.Map(1)); 62645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory()); 62745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 62845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // defined(OS_WIN) 62945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 63045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// iOS does not allow multiple processes. 63145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android ashmem does not support named shared memory. 63245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Mac SharedMemory does not support named shared memory. crbug.com/345734 63345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 63445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// On POSIX it is especially important we test shmem across processes, 63545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// not just across threads. But the test is enabled on all platforms. 63645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass SharedMemoryProcessTest : public MultiProcessTest { 63745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public: 63845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static void CleanUp() { 63945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 64045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Delete(s_test_name_); 64145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 64245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 64345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static int TaskTestMain() { 64445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int errors = 0; 64545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 64645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 64745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 64845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (rv != true) 64945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko errors++; 65045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory.Map(s_data_size_); 65145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(rv); 65245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (rv != true) 65345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko errors++; 65445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int* ptr = static_cast<int*>(memory.memory()); 65545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 65645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // This runs concurrently in multiple processes. Writes need to be atomic. 65745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko subtle::Barrier_AtomicIncrement(ptr, 1); 65845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Close(); 65945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return errors; 66045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 66145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 66245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static const char s_test_name_[]; 66345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko static const uint32_t s_data_size_; 66445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}; 66545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 66645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst char SharedMemoryProcessTest::s_test_name_[] = "MPMem"; 66745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst uint32_t SharedMemoryProcessTest::s_data_size_ = 1024; 66845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 66945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { 67045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const int kNumTasks = 5; 67145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 67245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryProcessTest::CleanUp(); 67345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 67445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Create a shared memory region. Set the first word to 0. 67545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemory memory; 67645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 67745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(rv); 67845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko rv = memory.Map(s_data_size_); 67945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_TRUE(rv); 68045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int* ptr = static_cast<int*>(memory.memory()); 68145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko *ptr = 0; 68245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 68345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Start |kNumTasks| processes, each of which atomically increments the first 68445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // word by 1. 685319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski SpawnChildResult children[kNumTasks]; 68645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int index = 0; index < kNumTasks; ++index) { 687319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski children[index] = SpawnChild("SharedMemoryTestMain"); 688319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ASSERT_TRUE(children[index].process.IsValid()); 68945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 69045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 69145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Check that each process exited correctly. 69245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int exit_code = 0; 69345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (int index = 0; index < kNumTasks; ++index) { 694319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski EXPECT_TRUE(children[index].process.WaitForExit(&exit_code)); 69545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_EQ(0, exit_code); 69645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 69745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 69845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // Check that the shared memory region reflects |kNumTasks| increments. 69945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ASSERT_EQ(kNumTasks, *ptr); 70045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 70145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko memory.Close(); 70245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko SharedMemoryProcessTest::CleanUp(); 70345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 70445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 70545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoMULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { 70645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return SharedMemoryProcessTest::TaskTestMain(); 70745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 70845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 70945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 71045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} // namespace base 711