shared_memory_unittest.cc revision 36040ed30c39d2106a2cd5ec033e98b71302a744
1d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Use of this source code is governed by a BSD-style license that can be 3d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// found in the LICENSE file. 4d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 5d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/memory/shared_memory.h" 6d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 7d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <stddef.h> 8d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <stdint.h> 9d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 10d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <memory> 11d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 12d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/atomicops.h" 13d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/macros.h" 14d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/memory/shared_memory_handle.h" 15d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/process/kill.h" 16d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/rand_util.h" 17d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/strings/string_number_conversions.h" 18d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/sys_info.h" 19d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/test/multiprocess_test.h" 20d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/threading/platform_thread.h" 21d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/time/time.h" 22d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "build/build_config.h" 23d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "testing/gtest/include/gtest/gtest.h" 24d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "testing/multiprocess_func_list.h" 25a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen 26d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_POSIX) 27d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <errno.h> 287e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti#include <fcntl.h> 290c57e5931daabf22632ad49f2ad0657df59b858bFederico Tomassetti#include <sys/mman.h> 30f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti#include <sys/stat.h> 31f8f8a6fc81e2d717568c0ab9895605c1f4b69bbcFederico Tomassetti#include <sys/types.h> 32d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <unistd.h> 33d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif 34d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 35de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti#if defined(OS_WIN) 36d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/win/scoped_handle.h" 3703df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#endif 3803df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti 399e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassettinamespace base { 4003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti 41d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassettinamespace { 4215cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti 43d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if !defined(OS_MACOSX) 44d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Each thread will open the shared memory. Each thread will take a different 4 45d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// byte int pointer, and keep changing it, with some small pauses in between. 46d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Verify that each thread's value in the shared memory is always correct. 47d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetticlass MultipleThreadMain : public PlatformThread::Delegate { 48d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti public: 49d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti explicit MultipleThreadMain(int16_t id) : id_(id) {} 50d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti ~MultipleThreadMain() override {} 51d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 52d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti static void CleanUp() { 5383d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen SharedMemory memory; 546a1ee724c337694ee28b2a09af41c236b880ba66Danny van Bruggen memory.Delete(s_test_name_); 558324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen } 56d4db09d04aca5a9df4278652d55d680c4a826efcFederico Tomassetti 5748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen // PlatformThread::Delegate interface. 5840d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti void ThreadMain() override { 59d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti const uint32_t kDataSize = 1024; 60d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemory memory; 619a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); 628324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen EXPECT_TRUE(rv); 63d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory.Map(kDataSize); 64d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_TRUE(rv); 65d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti int* ptr = static_cast<int*>(memory.memory()) + id_; 66a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen EXPECT_EQ(0, *ptr); 67a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen 68a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen for (int idx = 0; idx < 100; idx++) { 6948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen *ptr = idx; 7048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 71a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen EXPECT_EQ(*ptr, idx); 72d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 73d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti // Reset back to 0 for the next test that uses the same name. 74d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti *ptr = 0; 75d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 76d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti memory.Close(); 77d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 7848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 796149218487aac50fad2256c8723639671747d7bbDanny van Bruggen private: 80d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti int16_t id_; 8140d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti 8240d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti static const char s_test_name_[]; 83d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 8440d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); 8540d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti}; 8640d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti 8740d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetticonst char MultipleThreadMain::s_test_name_[] = 888324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen "SharedMemoryOpenThreadTest"; 89d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif // !defined(OS_MACOSX) 90d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 91d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti} // namespace 92dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen 93dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen// Android/Mac doesn't support SharedMemory::Open/Delete/ 94dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen// CreateNamedDeprecated(openExisting=true) 95dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen#if !defined(OS_ANDROID) && !defined(OS_MACOSX) 9648789abfd3738d660abb6f8cd758a40c57379597Danny van BruggenTEST(SharedMemoryTest, OpenClose) { 9748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen const uint32_t kDataSize = 1024; 9848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen std::string test_name = "SharedMemoryOpenCloseTest"; 9948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 100dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen // Open two handles to a memory segment, confirm that they are mapped 10148789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen // separately yet point to the same space. 102dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen SharedMemory memory1; 103dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen bool rv = memory1.Delete(test_name); 104dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen EXPECT_TRUE(rv); 1058324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen rv = memory1.Delete(test_name); 1066149218487aac50fad2256c8723639671747d7bbDanny van Bruggen EXPECT_TRUE(rv); 1078324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen rv = memory1.Open(test_name, false); 1088324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen EXPECT_FALSE(rv); 109d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 1107a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti EXPECT_TRUE(rv); 1116149218487aac50fad2256c8723639671747d7bbDanny van Bruggen rv = memory1.Map(kDataSize); 1127a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti EXPECT_TRUE(rv); 1138324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen SharedMemory memory2; 1148324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen rv = memory2.Open(test_name, false); 115dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen EXPECT_TRUE(rv); 116d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory2.Map(kDataSize); 1179a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen EXPECT_TRUE(rv); 1186149218487aac50fad2256c8723639671747d7bbDanny van Bruggen EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. 1196149218487aac50fad2256c8723639671747d7bbDanny van Bruggen 1206149218487aac50fad2256c8723639671747d7bbDanny van Bruggen // Make sure we don't segfault. (it actually happened!) 121d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); 1226149218487aac50fad2256c8723639671747d7bbDanny van Bruggen ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); 1236149218487aac50fad2256c8723639671747d7bbDanny van Bruggen 1246149218487aac50fad2256c8723639671747d7bbDanny van Bruggen // Write data to the first memory segment, verify contents of second. 1256149218487aac50fad2256c8723639671747d7bbDanny van Bruggen memset(memory1.memory(), '1', kDataSize); 1266149218487aac50fad2256c8723639671747d7bbDanny van Bruggen EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); 1276149218487aac50fad2256c8723639671747d7bbDanny van Bruggen 1286149218487aac50fad2256c8723639671747d7bbDanny van Bruggen // Close the first memory segment, and verify the second has the right data. 1296149218487aac50fad2256c8723639671747d7bbDanny van Bruggen memory1.Close(); 1306149218487aac50fad2256c8723639671747d7bbDanny van Bruggen char* start_ptr = static_cast<char*>(memory2.memory()); 1316149218487aac50fad2256c8723639671747d7bbDanny van Bruggen char* end_ptr = start_ptr + kDataSize; 132d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti for (char* ptr = start_ptr; ptr < end_ptr; ptr++) 133d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(*ptr, '1'); 134d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 13540d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti // Close the second memory segment. 13640d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti memory2.Close(); 137d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 138d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory1.Delete(test_name); 1395e40a8838a5118df43a847ce8c52dddac0843b22Federico Tomassetti EXPECT_TRUE(rv); 140d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory2.Delete(test_name); 141d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_TRUE(rv); 142793f207b1b17498cdb201309ba94c25cb9e4fe20Federico Tomassetti} 14308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 14408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico TomassettiTEST(SharedMemoryTest, OpenExclusive) { 14508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti const uint32_t kDataSize = 1024; 1466149218487aac50fad2256c8723639671747d7bbDanny van Bruggen const uint32_t kDataSize2 = 2048; 1477a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti std::ostringstream test_name_stream; 14808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti test_name_stream << "SharedMemoryOpenExclusiveTest." 14908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti << Time::Now().ToDoubleT(); 15048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen std::string test_name = test_name_stream.str(); 1516a1ee724c337694ee28b2a09af41c236b880ba66Danny van Bruggen 1527a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti // Open two handles to a memory segment and check that 15308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // open_existing_deprecated works as expected. 15448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen SharedMemory memory1; 15583d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize); 15648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen EXPECT_TRUE(rv); 15708bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 15808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // Memory1 knows it's size because it created it. 15908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti EXPECT_EQ(memory1.requested_size(), kDataSize); 16008bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 16108bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti rv = memory1.Map(kDataSize); 1629192b9d17903947058b755b987d1c57a05821e58Danny van Bruggen EXPECT_TRUE(rv); 16308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 16408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // The mapped memory1 must be at least the size we asked for. 16508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti EXPECT_GE(memory1.mapped_size(), kDataSize); 16608bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 16708bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // The mapped memory1 shouldn't exceed rounding for allocation granularity. 168516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti EXPECT_LT(memory1.mapped_size(), 16908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti kDataSize + SysInfo::VMAllocationGranularity()); 17048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 17183d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen memset(memory1.memory(), 'G', kDataSize); 17248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 17308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti SharedMemory memory2; 17408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // Should not be able to create if openExisting is false. 17508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); 17648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen EXPECT_FALSE(rv); 17783d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen 17808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti // Should be able to create with openExisting true. 17908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); 18008bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti EXPECT_TRUE(rv); 18108bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti 182793f207b1b17498cdb201309ba94c25cb9e4fe20Federico Tomassetti // Memory2 shouldn't know the size because we didn't create it. 1836149218487aac50fad2256c8723639671747d7bbDanny van Bruggen EXPECT_EQ(memory2.requested_size(), 0U); 184f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti 185f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti // We should be able to map the original size. 186f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti rv = memory2.Map(kDataSize); 187f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti EXPECT_TRUE(rv); 188c73ae5d79b62de91209477538b45ab5216fb108eFederico Tomassetti 189c73ae5d79b62de91209477538b45ab5216fb108eFederico Tomassetti // The mapped memory2 must be at least the size of the original. 190d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_GE(memory2.mapped_size(), kDataSize); 191d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 192d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti // The mapped memory2 shouldn't exceed rounding for allocation granularity. 19315cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti EXPECT_LT(memory2.mapped_size(), 1946149218487aac50fad2256c8723639671747d7bbDanny van Bruggen kDataSize2 + SysInfo::VMAllocationGranularity()); 195d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 19646d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen // Verify that opening memory2 didn't truncate or delete memory 1. 197d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti char* start_ptr = static_cast<char*>(memory2.memory()); 19848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen char* end_ptr = start_ptr + kDataSize; 199d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { 200d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(*ptr, 'G'); 201d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 202d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 203ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti memory1.Close(); 204ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti memory2.Close(); 20515cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti 2066149218487aac50fad2256c8723639671747d7bbDanny van Bruggen rv = memory1.Delete(test_name); 20746d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen EXPECT_TRUE(rv); 208ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti} 209d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) 210d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 211d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Check that memory is still mapped after its closed. 2126149218487aac50fad2256c8723639671747d7bbDanny van BruggenTEST(SharedMemoryTest, CloseNoUnmap) { 213198c4d502c00c07c674543bfb1eebedafcf4b193Federico Tomassetti const size_t kDataSize = 4096; 214d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 2158a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik SharedMemory memory; 2168a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 2178a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik char* ptr = static_cast<char*>(memory.memory()); 2188324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen ASSERT_NE(ptr, static_cast<void*>(NULL)); 2193608acd141a4d3c2105672b4b19b26e4d2badb5cDanny van Bruggen memset(ptr, 'G', kDataSize); 2202a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik 2212a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik memory.Close(); 2222a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik 2232a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik EXPECT_EQ(ptr, memory.memory()); 224d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); 225d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 226d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti for (size_t i = 0; i < kDataSize; i++) { 227d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ('G', ptr[i]); 228d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 229d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 230d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti memory.Unmap(); 231d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(nullptr, memory.memory()); 232d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti} 233d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 2349a7cda9c8fb4cbb33b5f38daea68921ae201ef31Federico Tomassetti#if !defined(OS_MACOSX) 2356149218487aac50fad2256c8723639671747d7bbDanny van Bruggen// Create a set of N threads to each open a shared memory segment and write to 2369a7cda9c8fb4cbb33b5f38daea68921ae201ef31Federico Tomassetti// it. Verify that they are always reading/writing consistent data. 237d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, MultipleThreads) { 238d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti const int kNumThreads = 5; 239d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 240d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti MultipleThreadMain::CleanUp(); 2412a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // On POSIX we have a problem when 2 threads try to create the shmem 2422a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // (a file) at exactly the same time, since create both creates the 2432a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // file and zerofills it. We solve the problem for this unit test 2442a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // (make it not flaky) by starting with 1 thread, then 2452a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // intentionally don't clean up its shmem before running with 2462a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // kNumThreads. 2472a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik 2482a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik int threadcounts[] = { 1, kNumThreads }; 2492a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik for (size_t i = 0; i < arraysize(threadcounts); i++) { 2502a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik int numthreads = threadcounts[i]; 2512a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik std::unique_ptr<PlatformThreadHandle[]> thread_handles; 2522a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik std::unique_ptr<MultipleThreadMain* []> thread_delegates; 2532a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik 2542a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik thread_handles.reset(new PlatformThreadHandle[numthreads]); 2552a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik thread_delegates.reset(new MultipleThreadMain*[numthreads]); 2562a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik 2572a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik // Spawn the threads. 2586149218487aac50fad2256c8723639671747d7bbDanny van Bruggen for (int16_t index = 0; index < numthreads; index++) { 259d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti PlatformThreadHandle pth; 260d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti thread_delegates[index] = new MultipleThreadMain(index); 261d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 262d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti thread_handles[index] = pth; 263d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 264f671c0e58dbbe6688926060fee6a9b6cbc9d8f76Federico Tomassetti 265516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti // Wait for the threads to finish. 266516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti for (int index = 0; index < numthreads; index++) { 267516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti PlatformThread::Join(thread_handles[index]); 2686149218487aac50fad2256c8723639671747d7bbDanny van Bruggen delete thread_delegates[index]; 269f671c0e58dbbe6688926060fee6a9b6cbc9d8f76Federico Tomassetti } 270d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 271d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti MultipleThreadMain::CleanUp(); 2723608acd141a4d3c2105672b4b19b26e4d2badb5cDanny van Bruggen} 273d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif 27448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 2756149218487aac50fad2256c8723639671747d7bbDanny van Bruggen// Allocate private (unique) shared memory with an empty string for a 276d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// name. Make sure several of them don't point to the same thing as 2772a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik// we might expect if the names are equal. 278d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, AnonymousPrivate) { 279de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti int i, j; 280de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti int count = 4; 281de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti bool rv; 2826149218487aac50fad2256c8723639671747d7bbDanny van Bruggen const uint32_t kDataSize = 8192; 283de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti 28446d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]); 285de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti std::unique_ptr<int* []> pointers(new int*[count]); 286de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti ASSERT_TRUE(memories.get()); 287de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti ASSERT_TRUE(pointers.get()); 288de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti 289de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti for (i = 0; i < count; i++) { 290de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti rv = memories[i].CreateAndMapAnonymous(kDataSize); 291de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti EXPECT_TRUE(rv); 292de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti int* ptr = static_cast<int*>(memories[i].memory()); 293de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti EXPECT_TRUE(ptr); 294de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti pointers[i] = ptr; 295de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti } 296de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti 297de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti for (i = 0; i < count; i++) { 298de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti // zero out the first int in each except for i; for that one, make it 100. 299de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti for (j = 0; j < count; j++) { 300de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti if (i == j) 301de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti pointers[j][0] = 100; 302dea490b3c4b649d5ede5f12dbf6740b816681cf2Federico Tomassetti else 303de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti pointers[j][0] = 0; 304de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti } 305de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti // make sure there is no bleeding of the 100 into the other pointers 306de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti for (j = 0; j < count; j++) { 307d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti if (i == j) 308d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(100, pointers[j][0]); 309d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti else 310d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ(0, pointers[j][0]); 311d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 312d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 3136149218487aac50fad2256c8723639671747d7bbDanny van Bruggen 314d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti for (int i = 0; i < count; i++) { 315d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti memories[i].Close(); 316d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti } 317d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti} 318d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 319d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, ShareReadOnly) { 320d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti StringPiece contents = "Hello World"; 321d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 322d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemory writable_shmem; 323d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemoryCreateOptions options; 324d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti options.size = contents.size(); 325d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti options.share_read_only = true; 3266149218487aac50fad2256c8723639671747d7bbDanny van Bruggen#if defined(OS_MACOSX) && !defined(OS_IOS) 327a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen // The Mach functionality is tested in shared_memory_mac_unittest.cc. 328eeb2701b8cbc85c513d0759d6fa3f2fc41b81ebcFederico Tomassetti options.type = SharedMemoryHandle::POSIX; 329d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif 330a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen ASSERT_TRUE(writable_shmem.Create(options)); 331eeb2701b8cbc85c513d0759d6fa3f2fc41b81ebcFederico Tomassetti ASSERT_TRUE(writable_shmem.Map(options.size)); 332d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti memcpy(writable_shmem.memory(), contents.data(), contents.size()); 333d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_TRUE(writable_shmem.Unmap()); 334d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 335d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemoryHandle readonly_handle; 336d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(), 337d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti &readonly_handle)); 33848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true); 339de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti 34048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen ASSERT_TRUE(readonly_shmem.Map(contents.size())); 341dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti EXPECT_EQ(contents, 342521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti StringPiece(static_cast<const char*>(readonly_shmem.memory()), 34383d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen contents.size())); 344521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti EXPECT_TRUE(readonly_shmem.Unmap()); 345521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti 34683d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen // Make sure the writable instance is still writable. 347521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti ASSERT_TRUE(writable_shmem.Map(contents.size())); 348521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti StringPiece new_contents = "Goodbye"; 34983d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size()); 350521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti EXPECT_EQ(new_contents, 351521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti StringPiece(static_cast<const char*>(writable_shmem.memory()), 35283d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen new_contents.size())); 353521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti 354dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti // We'd like to check that if we send the read-only segment to another 35583d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen // process, then that other process can't reopen it read/write. (Since that 356dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti // would be a security hole.) Setting up multiple processes is hard in a 357521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti // unittest, so this test checks that the *current* process can't reopen the 35883d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen // segment read/write. I think the test here is stronger than we actually 359521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti // care about, but there's a remote possibility that sending a file over a 360521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti // pipe would transform it into read/write. 36183d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen SharedMemoryHandle handle = readonly_shmem.handle(); 362521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti 363521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti#if defined(OS_ANDROID) 36483d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen // The "read-only" handle is still writable on Android: 365521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti // http://crbug.com/320865 366dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti (void)handle; 367dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti#elif defined(OS_POSIX) 368dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle); 36948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE) 370de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti << "The descriptor itself should be read-only."; 371f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti 37248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen errno = 0; 37348789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE, 374f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti MAP_SHARED, handle_fd, 0); 375de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti int mmap_errno = errno; 37648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen EXPECT_EQ(MAP_FAILED, writable) 37703df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti << "It shouldn't be possible to re-mmap the descriptor writable."; 37803df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); 3796149218487aac50fad2256c8723639671747d7bbDanny van Bruggen if (writable != MAP_FAILED) 38003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); 38187b56cb1f18252c95d88b979a449f06d55def290Federico Tomassetti 38287db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti#elif defined(OS_WIN) 38387b56cb1f18252c95d88b979a449f06d55def290Federico Tomassetti EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0)) 38487db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti << "Shouldn't be able to map memory writable."; 38503df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti 38648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen HANDLE temp_handle; 38746d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 38887db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti GetCurrentProcess(), &temp_handle, 38987db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti FILE_MAP_ALL_ACCESS, false, 0); 39003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti EXPECT_EQ(FALSE, rv) 39103df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti << "Shouldn't be able to duplicate the handle into a writable one."; 3929e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti if (rv) 3939e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti win::ScopedHandle writable_handle(temp_handle); 39487db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), 39587db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti GetCurrentProcess(), &temp_handle, FILE_MAP_READ, 39687db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti false, 0); 39787db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti EXPECT_EQ(TRUE, rv) 3989e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti << "Should be able to duplicate the handle into a readable one."; 39948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen if (rv) 4009e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti win::ScopedHandle writable_handle(temp_handle); 40103df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#else 40203df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#error Unexpected platform; write a test that tries to make 'handle' writable. 40303df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#endif // defined(OS_POSIX) || defined(OS_WIN) 40403df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti} 4057e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti 4067e85803c3a66d340e1cbdbc6c98081104ad412c3Federico TomassettiTEST(SharedMemoryTest, ShareToSelf) { 4077e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti StringPiece contents = "Hello World"; 4089a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen 40948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen SharedMemory shmem; 41048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); 41148789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen memcpy(shmem.memory(), contents.data(), contents.size()); 41248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen EXPECT_TRUE(shmem.Unmap()); 41348789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen 41448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen SharedMemoryHandle shared_handle; 41548789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 41648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen#if defined(OS_WIN) 41748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 4187e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti#endif 41903df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti SharedMemory shared(shared_handle, /*readonly=*/false); 420d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 421d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti ASSERT_TRUE(shared.Map(contents.size())); 422d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_EQ( 4236149218487aac50fad2256c8723639671747d7bbDanny van Bruggen contents, 424a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen StringPiece(static_cast<const char*>(shared.memory()), contents.size())); 4256149218487aac50fad2256c8723639671747d7bbDanny van Bruggen 426a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen shared_handle = SharedMemoryHandle(); 427fab5a9b624d0748ef3e924573f55386010a2694eFederico Tomassetti ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle)); 428d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_WIN) 429a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen ASSERT_TRUE(shared_handle.OwnershipPassesToIPC()); 430d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif 431d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemory readonly(shared_handle, /*readonly=*/true); 4324002ee095f065fb93ce3ad4355bc5fb7b63dafaaFederico Tomassetti 4336149218487aac50fad2256c8723639671747d7bbDanny van Bruggen ASSERT_TRUE(readonly.Map(contents.size())); 434152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti EXPECT_EQ(contents, 435de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti StringPiece(static_cast<const char*>(readonly.memory()), 436de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti contents.size())); 437de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti} 43883d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen 4399192b9d17903947058b755b987d1c57a05821e58Danny van BruggenTEST(SharedMemoryTest, MapAt) { 440152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t)); 441152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti const size_t kCount = SysInfo::VMAllocationGranularity(); 442152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti const size_t kDataSize = kCount * sizeof(uint32_t); 443152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti 444152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti SharedMemory memory; 445152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); 44648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen uint32_t* ptr = static_cast<uint32_t*>(memory.memory()); 447152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti ASSERT_NE(ptr, static_cast<void*>(NULL)); 448152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti 449de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti for (size_t i = 0; i < kCount; ++i) { 450de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti ptr[i] = i; 451152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti } 452de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti 453de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti memory.Unmap(); 454d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 455d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti off_t offset = SysInfo::VMAllocationGranularity(); 456d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset)); 457d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti offset /= sizeof(uint32_t); 458d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti ptr = static_cast<uint32_t*>(memory.memory()); 459d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti ASSERT_NE(ptr, static_cast<void*>(NULL)); 460d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti for (size_t i = offset; i < kCount; ++i) { 461d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti EXPECT_EQ(ptr[i - offset], i); 462d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti } 463d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti} 464d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti 465d6aebf46978852659303ad0fe057e1cddd9e391dFederico TomassettiTEST(SharedMemoryTest, MapTwice) { 466d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti const uint32_t kDataSize = 1024; 467a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen SharedMemory memory; 468d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti bool rv = memory.CreateAndMapAnonymous(kDataSize); 469d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti EXPECT_TRUE(rv); 470d533531b8d35f2d899f9e826e1993a16226e7580Federico Tomassetti 471d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti void* old_address = memory.memory(); 472d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 473d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti rv = memory.Map(kDataSize); 474d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti EXPECT_FALSE(rv); 4751fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti EXPECT_EQ(old_address, memory.memory()); 4761fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti} 4771fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti 4781fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti#if defined(OS_POSIX) 47948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen// This test is not applicable for iOS (crbug.com/399384). 480d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if !defined(OS_IOS) 481d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC. 482d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, AnonymousExecutable) { 483d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti const uint32_t kTestSize = 1 << 16; 484d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 485d4db09d04aca5a9df4278652d55d680c4a826efcFederico Tomassetti SharedMemory shared_memory; 486d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti SharedMemoryCreateOptions options; 487d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti options.size = kTestSize; 488d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti options.executable = true; 489d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_MACOSX) && !defined(OS_IOS) 490d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti // The Mach functionality is tested in shared_memory_mac_unittest.cc. 491d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti options.type = SharedMemoryHandle::POSIX; 49248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen#endif 493d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti 494d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti EXPECT_TRUE(shared_memory.Create(options)); 495d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size())); 496d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti 497d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(), 498d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti PROT_READ | PROT_EXEC)); 499d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti} 500d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti#endif // !defined(OS_IOS) 501d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti 502d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti// Android supports a different permission model than POSIX for its "ashmem" 503d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// shared memory implementation. So the tests about file permissions are not 504d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// included on Android. 505d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti#if !defined(OS_ANDROID) 506d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti 507d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Set a umask and restore the old mask on destruction. 508class ScopedUmaskSetter { 509 public: 510 explicit ScopedUmaskSetter(mode_t target_mask) { 511 old_umask_ = umask(target_mask); 512 } 513 ~ScopedUmaskSetter() { umask(old_umask_); } 514 private: 515 mode_t old_umask_; 516 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 517}; 518 519// Create a shared memory object, check its permissions. 520TEST(SharedMemoryTest, FilePermissionsAnonymous) { 521 const uint32_t kTestSize = 1 << 8; 522 523 SharedMemory shared_memory; 524 SharedMemoryCreateOptions options; 525 options.size = kTestSize; 526#if defined(OS_MACOSX) && !defined(OS_IOS) 527 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 528 options.type = SharedMemoryHandle::POSIX; 529#endif 530 // Set a file mode creation mask that gives all permissions. 531 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 532 533 EXPECT_TRUE(shared_memory.Create(options)); 534 535 int shm_fd = 536 SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 537 struct stat shm_stat; 538 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); 539 // Neither the group, nor others should be able to read the shared memory 540 // file. 541 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 542 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 543} 544 545// Create a shared memory object, check its permissions. 546TEST(SharedMemoryTest, FilePermissionsNamed) { 547 const uint32_t kTestSize = 1 << 8; 548 549 SharedMemory shared_memory; 550 SharedMemoryCreateOptions options; 551 options.size = kTestSize; 552#if defined(OS_MACOSX) && !defined(OS_IOS) 553 // The Mach functionality is tested in shared_memory_mac_unittest.cc. 554 options.type = SharedMemoryHandle::POSIX; 555#endif 556 557 // Set a file mode creation mask that gives all permissions. 558 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); 559 560 EXPECT_TRUE(shared_memory.Create(options)); 561 562 int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); 563 struct stat shm_stat; 564 EXPECT_EQ(0, fstat(fd, &shm_stat)); 565 // Neither the group, nor others should have been able to open the shared 566 // memory file while its name existed. 567 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); 568 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); 569} 570#endif // !defined(OS_ANDROID) 571 572#endif // defined(OS_POSIX) 573 574// Map() will return addresses which are aligned to the platform page size, this 575// varies from platform to platform though. Since we'd like to advertise a 576// minimum alignment that callers can count on, test for it here. 577TEST(SharedMemoryTest, MapMinimumAlignment) { 578 static const int kDataSize = 8192; 579 580 SharedMemory shared_memory; 581 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); 582 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( 583 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 584 shared_memory.Close(); 585} 586 587#if defined(OS_WIN) 588TEST(SharedMemoryTest, UnsafeImageSection) { 589 const char kTestSectionName[] = "UnsafeImageSection"; 590 wchar_t path[MAX_PATH]; 591 EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U); 592 593 // Map the current executable image to save us creating a new PE file on disk. 594 base::win::ScopedHandle file_handle(::CreateFile( 595 path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); 596 EXPECT_TRUE(file_handle.IsValid()); 597 base::win::ScopedHandle section_handle( 598 ::CreateFileMappingA(file_handle.Get(), nullptr, 599 PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName)); 600 EXPECT_TRUE(section_handle.IsValid()); 601 602 // Check direct opening by name, from handle and duplicated from handle. 603 SharedMemory shared_memory_open; 604 EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true)); 605 EXPECT_FALSE(shared_memory_open.Map(1)); 606 EXPECT_EQ(nullptr, shared_memory_open.memory()); 607 608 SharedMemory shared_memory_handle_local( 609 SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true); 610 EXPECT_FALSE(shared_memory_handle_local.Map(1)); 611 EXPECT_EQ(nullptr, shared_memory_handle_local.memory()); 612 613 // Check that a handle without SECTION_QUERY also can't be mapped as it can't 614 // be checked. 615 SharedMemory shared_memory_handle_dummy; 616 SharedMemoryCreateOptions options; 617 options.size = 0x1000; 618 EXPECT_TRUE(shared_memory_handle_dummy.Create(options)); 619 HANDLE handle_no_query; 620 EXPECT_TRUE(::DuplicateHandle( 621 ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(), 622 ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0)); 623 SharedMemory shared_memory_handle_no_query( 624 SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true); 625 EXPECT_FALSE(shared_memory_handle_no_query.Map(1)); 626 EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory()); 627} 628#endif // defined(OS_WIN) 629 630// iOS does not allow multiple processes. 631// Android ashmem does not support named shared memory. 632// Mac SharedMemory does not support named shared memory. crbug.com/345734 633#if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 634// On POSIX it is especially important we test shmem across processes, 635// not just across threads. But the test is enabled on all platforms. 636class SharedMemoryProcessTest : public MultiProcessTest { 637 public: 638 static void CleanUp() { 639 SharedMemory memory; 640 memory.Delete(s_test_name_); 641 } 642 643 static int TaskTestMain() { 644 int errors = 0; 645 SharedMemory memory; 646 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 647 EXPECT_TRUE(rv); 648 if (rv != true) 649 errors++; 650 rv = memory.Map(s_data_size_); 651 EXPECT_TRUE(rv); 652 if (rv != true) 653 errors++; 654 int* ptr = static_cast<int*>(memory.memory()); 655 656 // This runs concurrently in multiple processes. Writes need to be atomic. 657 subtle::Barrier_AtomicIncrement(ptr, 1); 658 memory.Close(); 659 return errors; 660 } 661 662 static const char s_test_name_[]; 663 static const uint32_t s_data_size_; 664}; 665 666const char SharedMemoryProcessTest::s_test_name_[] = "MPMem"; 667const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024; 668 669TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { 670 const int kNumTasks = 5; 671 672 SharedMemoryProcessTest::CleanUp(); 673 674 // Create a shared memory region. Set the first word to 0. 675 SharedMemory memory; 676 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); 677 ASSERT_TRUE(rv); 678 rv = memory.Map(s_data_size_); 679 ASSERT_TRUE(rv); 680 int* ptr = static_cast<int*>(memory.memory()); 681 *ptr = 0; 682 683 // Start |kNumTasks| processes, each of which atomically increments the first 684 // word by 1. 685 Process processes[kNumTasks]; 686 for (int index = 0; index < kNumTasks; ++index) { 687 processes[index] = SpawnChild("SharedMemoryTestMain"); 688 ASSERT_TRUE(processes[index].IsValid()); 689 } 690 691 // Check that each process exited correctly. 692 int exit_code = 0; 693 for (int index = 0; index < kNumTasks; ++index) { 694 EXPECT_TRUE(processes[index].WaitForExit(&exit_code)); 695 EXPECT_EQ(0, exit_code); 696 } 697 698 // Check that the shared memory region reflects |kNumTasks| increments. 699 ASSERT_EQ(kNumTasks, *ptr); 700 701 memory.Close(); 702 SharedMemoryProcessTest::CleanUp(); 703} 704 705MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { 706 return SharedMemoryProcessTest::TaskTestMain(); 707} 708#endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) 709 710} // namespace base 711