shared_memory_unittest.cc 22 KB

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