Add switch to always use temp dir in shared memory instances on Linux builds
Modify GetShmemTempDir to check for a runtime switch to always use the temp dir
Changes tests in shared_memory_unittest.cc to be parameterized and
test also for when /dev/shm is disabled.
Bug: 736452,792117
Change-Id: Id930ea525980e97c4ab70e37689301370776fc79
Reviewed-on: https://chromium-review.googlesource.com/810325
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: David Vallet <dvallet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523959}
diff --git a/base/base_switches.cc b/base/base_switches.cc
index 9554233..870d55c 100644
--- a/base/base_switches.cc
+++ b/base/base_switches.cc
@@ -112,6 +112,14 @@
const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect";
#endif
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// The /dev/shm partition is too small in certain VM environments, causing
+// Chrome to fail or crash (see http://crbug.com/715363). Use this flag to
+// work-around this issue (a temporary directory will always be used to create
+// anonymous shared memory files).
+const char kDisableDevShmUsage[] = "disable-dev-shm-usage";
+#endif
+
#if defined(OS_POSIX)
// Used for turning on Breakpad crash reporting in a debug environment where
// crash reporting is typically compiled but disabled.
diff --git a/base/base_switches.h b/base/base_switches.h
index 56be306..55c8ed2 100644
--- a/base/base_switches.h
+++ b/base/base_switches.h
@@ -37,6 +37,10 @@
extern const char kDisableUsbKeyboardDetect[];
#endif
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+extern const char kDisableDevShmUsage[];
+#endif
+
#if defined(OS_POSIX)
extern const char kEnableCrashReporterForTesting[];
#endif
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 553192f..447ff50 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -21,6 +21,8 @@
#include <time.h>
#include <unistd.h>
+#include "base/base_switches.h"
+#include "base/command_line.h"
#include "base/containers/stack.h"
#include "base/environment.h"
#include "base/files/file_enumerator.h"
@@ -985,16 +987,21 @@
// This is implemented in file_util_android.cc for that platform.
bool GetShmemTempDir(bool executable, FilePath* path) {
#if defined(OS_LINUX) || defined(OS_AIX)
+ bool disable_dev_shm = false;
+#if !defined(OS_CHROMEOS)
+ disable_dev_shm = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDevShmUsage);
+#endif
bool use_dev_shm = true;
if (executable) {
static const bool s_dev_shm_executable = DetermineDevShmExecutable();
use_dev_shm = s_dev_shm_executable;
}
- if (use_dev_shm) {
+ if (use_dev_shm && !disable_dev_shm) {
*path = FilePath("/dev/shm");
return true;
}
-#endif
+#endif // defined(OS_LINUX) || defined(OS_AIX)
return GetTempDir(path);
}
#endif // !defined(OS_ANDROID)
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
index 19a12455..d3c31db 100644
--- a/base/memory/shared_memory_unittest.cc
+++ b/base/memory/shared_memory_unittest.cc
@@ -10,6 +10,8 @@
#include <memory>
#include "base/atomicops.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/shared_memory_handle.h"
#include "base/process/kill.h"
@@ -100,12 +102,36 @@
"SharedMemoryOpenThreadTest";
#endif // !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+enum class Mode {
+ Default,
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ DisableDevShm = 1,
+#endif
+};
+
+class SharedMemoryTest : public ::testing::TestWithParam<Mode> {
+ public:
+ void SetUp() override {
+ switch (GetParam()) {
+ case Mode::Default:
+ break;
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ case Mode::DisableDevShm:
+ CommandLine* cmdline = CommandLine::ForCurrentProcess();
+ cmdline->AppendSwitch(switches::kDisableDevShmUsage);
+ break;
+#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ }
+ }
+};
+
} // namespace
// Android/Mac/Fuchsia doesn't support SharedMemory::Open/Delete/
// CreateNamedDeprecated(openExisting=true)
#if !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-TEST(SharedMemoryTest, OpenClose) {
+
+TEST_P(SharedMemoryTest, OpenClose) {
const uint32_t kDataSize = 1024;
std::string test_name = "SharedMemoryOpenCloseTest";
@@ -153,7 +179,7 @@
EXPECT_TRUE(rv);
}
-TEST(SharedMemoryTest, OpenExclusive) {
+TEST_P(SharedMemoryTest, OpenExclusive) {
const uint32_t kDataSize = 1024;
const uint32_t kDataSize2 = 2048;
std::ostringstream test_name_stream;
@@ -221,7 +247,7 @@
#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
// Check that memory is still mapped after its closed.
-TEST(SharedMemoryTest, CloseNoUnmap) {
+TEST_P(SharedMemoryTest, CloseNoUnmap) {
const size_t kDataSize = 4096;
SharedMemory memory;
@@ -246,7 +272,7 @@
#if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
// Create a set of N threads to each open a shared memory segment and write to
// it. Verify that they are always reading/writing consistent data.
-TEST(SharedMemoryTest, MultipleThreads) {
+TEST_P(SharedMemoryTest, MultipleThreads) {
const int kNumThreads = 5;
MultipleThreadMain::CleanUp();
@@ -287,7 +313,7 @@
// Allocate private (unique) shared memory with an empty string for a
// name. Make sure several of them don't point to the same thing as
// we might expect if the names are equal.
-TEST(SharedMemoryTest, AnonymousPrivate) {
+TEST_P(SharedMemoryTest, AnonymousPrivate) {
int i, j;
int count = 4;
bool rv;
@@ -328,7 +354,7 @@
}
}
-TEST(SharedMemoryTest, GetReadOnlyHandle) {
+TEST_P(SharedMemoryTest, GetReadOnlyHandle) {
StringPiece contents = "Hello World";
SharedMemory writable_shmem;
@@ -430,7 +456,7 @@
#endif // defined(OS_POSIX) || defined(OS_WIN)
}
-TEST(SharedMemoryTest, ShareToSelf) {
+TEST_P(SharedMemoryTest, ShareToSelf) {
StringPiece contents = "Hello World";
SharedMemory shmem;
@@ -461,7 +487,7 @@
contents.size()));
}
-TEST(SharedMemoryTest, ShareWithMultipleInstances) {
+TEST_P(SharedMemoryTest, ShareWithMultipleInstances) {
static const StringPiece kContents = "Hello World";
SharedMemory shmem;
@@ -505,7 +531,7 @@
ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), readonly_contents);
}
-TEST(SharedMemoryTest, MapAt) {
+TEST_P(SharedMemoryTest, MapAt) {
ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
const size_t kCount = SysInfo::VMAllocationGranularity();
const size_t kDataSize = kCount * sizeof(uint32_t);
@@ -531,7 +557,7 @@
}
}
-TEST(SharedMemoryTest, MapTwice) {
+TEST_P(SharedMemoryTest, MapTwice) {
const uint32_t kDataSize = 1024;
SharedMemory memory;
bool rv = memory.CreateAndMapAnonymous(kDataSize);
@@ -548,7 +574,7 @@
// This test is not applicable for iOS (crbug.com/399384).
#if !defined(OS_IOS)
// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
-TEST(SharedMemoryTest, AnonymousExecutable) {
+TEST_P(SharedMemoryTest, AnonymousExecutable) {
const uint32_t kTestSize = 1 << 16;
SharedMemory shared_memory;
@@ -588,7 +614,7 @@
};
// Create a shared memory object, check its permissions.
-TEST(SharedMemoryTest, FilePermissionsAnonymous) {
+TEST_P(SharedMemoryTest, FilePermissionsAnonymous) {
const uint32_t kTestSize = 1 << 8;
SharedMemory shared_memory;
@@ -614,7 +640,7 @@
}
// Create a shared memory object, check its permissions.
-TEST(SharedMemoryTest, FilePermissionsNamed) {
+TEST_P(SharedMemoryTest, FilePermissionsNamed) {
const uint32_t kTestSize = 1 << 8;
SharedMemory shared_memory;
@@ -645,7 +671,7 @@
// Map() will return addresses which are aligned to the platform page size, this
// varies from platform to platform though. Since we'd like to advertise a
// minimum alignment that callers can count on, test for it here.
-TEST(SharedMemoryTest, MapMinimumAlignment) {
+TEST_P(SharedMemoryTest, MapMinimumAlignment) {
static const int kDataSize = 8192;
SharedMemory shared_memory;
@@ -656,7 +682,7 @@
}
#if defined(OS_WIN)
-TEST(SharedMemoryTest, UnsafeImageSection) {
+TEST_P(SharedMemoryTest, UnsafeImageSection) {
const char kTestSectionName[] = "UnsafeImageSection";
wchar_t path[MAX_PATH];
EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
@@ -784,7 +810,7 @@
#endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) &&
// !defined(OS_FUCHSIA)
-TEST(SharedMemoryTest, MappedId) {
+TEST_P(SharedMemoryTest, MappedId) {
const uint32_t kDataSize = 1024;
SharedMemory memory;
SharedMemoryCreateOptions options;
@@ -809,4 +835,13 @@
EXPECT_TRUE(memory.mapped_id().is_empty());
}
+INSTANTIATE_TEST_CASE_P(Default,
+ SharedMemoryTest,
+ ::testing::Values(Mode::Default));
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+INSTANTIATE_TEST_CASE_P(SkipDevShm,
+ SharedMemoryTest,
+ ::testing::Values(Mode::DisableDevShm));
+#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+
} // namespace base