You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2015/04/11 00:36:24 UTC

[1/2] mesos git commit: Simplified ROOT_CGROUPS_Listen test.

Repository: mesos
Updated Branches:
  refs/heads/master 4b15b9608 -> b74d07229


Simplified ROOT_CGROUPS_Listen test.

Review: https://reviews.apache.org/r/32955


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/dd9a4d5e
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/dd9a4d5e
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/dd9a4d5e

Branch: refs/heads/master
Commit: dd9a4d5ec2944fe12003bafb267f386a6e08cc15
Parents: 4b15b96
Author: Chi Zhang <ch...@gmail.com>
Authored: Fri Apr 10 15:09:35 2015 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Apr 10 15:17:31 2015 -0700

----------------------------------------------------------------------
 src/tests/cgroups_tests.cpp | 70 +++++++++-------------------------------
 1 file changed, 15 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/dd9a4d5e/src/tests/cgroups_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cgroups_tests.cpp b/src/tests/cgroups_tests.cpp
index e18aed1..475f48a 100644
--- a/src/tests/cgroups_tests.cpp
+++ b/src/tests/cgroups_tests.cpp
@@ -536,17 +536,15 @@ TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_Listen)
     << "this test.\n"
     << "-------------------------------------------------------------";
 
-  // Disable oom killer.
-  ASSERT_SOME(cgroups::memory::oom::killer::disable(
-        hierarchy, TEST_CGROUPS_ROOT));
+  const Bytes limit =  Megabytes(64);
 
-  // Limit the memory usage of the test cgroup to 64MB.
   ASSERT_SOME(cgroups::memory::limit_in_bytes(
-      hierarchy, TEST_CGROUPS_ROOT, Megabytes(64)));
+      hierarchy, TEST_CGROUPS_ROOT, limit));
 
   // Listen on oom events for test cgroup.
   Future<Nothing> future =
     cgroups::memory::oom::listen(hierarchy, TEST_CGROUPS_ROOT);
+
   ASSERT_FALSE(future.isFailed());
 
   // Test the cancellation.
@@ -556,59 +554,21 @@ TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_Listen)
   future = cgroups::memory::oom::listen(hierarchy, TEST_CGROUPS_ROOT);
   ASSERT_FALSE(future.isFailed());
 
-  pid_t pid = ::fork();
-  ASSERT_NE(-1, pid);
-
-  if (pid > 0) {
-    // In parent process.
-    future.await(Seconds(5));
-
-    EXPECT_TRUE(future.isReady());
-
-    // Kill the child process.
-    EXPECT_NE(-1, ::kill(pid, SIGKILL));
-
-    // Wait for the child process.
-    int status;
-    EXPECT_NE(-1, ::waitpid((pid_t) -1, &status, 0));
-    ASSERT_TRUE(WIFSIGNALED(status));
-    EXPECT_EQ(SIGKILL, WTERMSIG(status));
-  } else {
-    // In child process. We try to trigger an oom here.
-    // Put self into the test cgroup.
-    Try<Nothing> assign =
-      cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid());
-
-    if (assign.isError()) {
-      std::cerr << "Failed to assign cgroup: " << assign.error() << std::endl;
-      abort();
-    }
-
-    // Blow up the memory.
-    size_t limit = 1024 * 1024 * 512;
-    void* buffer = NULL;
-
-    if (posix_memalign(&buffer, getpagesize(), limit) != 0) {
-      perror("Failed to allocate page-aligned memory, posix_memalign");
-      abort();
-    }
+  MemoryTestHelper helper;
+  ASSERT_SOME(helper.spawn());
+  ASSERT_SOME(helper.pid());
 
-    // We use mlock and memset here to make sure that the memory
-    // actually gets paged in and thus accounted for.
-    if (mlock(buffer, limit) != 0) {
-      perror("Failed to lock memory, mlock");
-      abort();
-    }
+  EXPECT_SOME(cgroups::assign(
+      hierarchy, TEST_CGROUPS_ROOT, helper.pid().get()));
 
-    if (memset(buffer, 1, limit) != buffer) {
-      perror("Failed to fill memory, memset");
-      abort();
-    }
+  // Request more RSS memory in the subprocess than the limit.
+  // NOTE: We enable the kernel oom killer in this test. If it were
+  // disabled, the subprocess might hang and the following call won't
+  // return. By enabling the oom killer, we let the subprocess get
+  // killed and expect that an error is returned.
+  EXPECT_ERROR(helper.increaseRSS(limit * 2));
 
-    // Should not reach here.
-    std::cerr << "OOM does not happen!" << std::endl;
-    abort();
-  }
+  AWAIT_READY(future);
 }
 
 


[2/2] mesos git commit: Simplified MemIsolatorTest.MemUsage.

Posted by ji...@apache.org.
Simplified MemIsolatorTest.MemUsage.

Review: https://reviews.apache.org/r/32956


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b74d0722
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b74d0722
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b74d0722

Branch: refs/heads/master
Commit: b74d072290daeb422e8333298dfe8c3742aa43e4
Parents: dd9a4d5
Author: Chi Zhang <ch...@gmail.com>
Authored: Fri Apr 10 15:19:40 2015 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Apr 10 15:34:27 2015 -0700

----------------------------------------------------------------------
 src/tests/isolator_tests.cpp | 201 ++++++++++++++------------------------
 1 file changed, 75 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/b74d0722/src/tests/isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/isolator_tests.cpp b/src/tests/isolator_tests.cpp
index 535e9af..46621e8 100644
--- a/src/tests/isolator_tests.cpp
+++ b/src/tests/isolator_tests.cpp
@@ -67,6 +67,7 @@
 #endif // __linux__
 
 #include "tests/flags.hpp"
+#include "tests/memory_test_helper.hpp"
 #include "tests/mesos.hpp"
 #include "tests/module.hpp"
 #include "tests/utils.hpp"
@@ -157,15 +158,18 @@ TYPED_TEST(CpuIsolatorTest, UserCpuUsage)
       Resources::parse("cpus:1.0").get());
 
   ContainerID containerId;
-  containerId.set_value("user_cpu_usage");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   const string& file = path::join(dir.get(), "mesos_isolator_test_ready");
 
@@ -263,15 +267,18 @@ TYPED_TEST(CpuIsolatorTest, SystemCpuUsage)
       Resources::parse("cpus:1.0").get());
 
   ContainerID containerId;
-  containerId.set_value("system_cpu_usage");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   const string& file = path::join(dir.get(), "mesos_isolator_test_ready");
 
@@ -377,15 +384,18 @@ TEST_F(LimitedCpuIsolatorTest, ROOT_CGROUPS_Cfs)
       Resources::parse("cpus:0.5").get());
 
   ContainerID containerId;
-  containerId.set_value("mesos_test_cfs_cpu_limit");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   // Generate random numbers to max out a single core. We'll run this for 0.5
   // seconds of wall time so it should consume approximately 250 ms of total
@@ -484,15 +494,18 @@ TEST_F(LimitedCpuIsolatorTest, ROOT_CGROUPS_Cfs_Big_Quota)
       Resources::parse("cpus:100.5").get());
 
   ContainerID containerId;
-  containerId.set_value("mesos_test_cfs_big_cpu_limit");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   int pipes[2];
   ASSERT_NE(-1, ::pipe(pipes));
@@ -563,15 +576,18 @@ TEST_F(LimitedCpuIsolatorTest, ROOT_CGROUPS_Pids_and_Tids)
       Resources::parse("cpus:0.5;mem:512").get());
 
   ContainerID containerId;
-  containerId.set_value("mesos_test_cpu_pids_and_tids");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   // Right after the creation of the cgroup, which happens in
   // 'prepare', we check that it is empty.
@@ -669,51 +685,6 @@ typedef ::testing::Types<
 TYPED_TEST_CASE(MemIsolatorTest, MemIsolatorTypes);
 
 
-// This function should be async-signal-safe but it isn't: at least
-// posix_memalign, mlock, memset and perror are not safe.
-int consumeMemory(const Bytes& _size, const Duration& duration, int pipes[2])
-{
-  // In child process.
-  while (::close(pipes[1]) == -1 && errno == EINTR);
-
-  // Wait until the parent signals us to continue.
-  char dummy;
-  ssize_t length;
-  while ((length = ::read(pipes[0], &dummy, sizeof(dummy))) == -1 &&
-         errno == EINTR);
-
-  if (length != sizeof(dummy)) {
-    ABORT("Failed to synchronize with parent");
-  }
-
-  while (::close(pipes[0]) == -1 && errno == EINTR);
-
-  size_t size = static_cast<size_t>(_size.bytes());
-  void* buffer = NULL;
-
-  if (posix_memalign(&buffer, getpagesize(), size) != 0) {
-    perror("Failed to allocate page-aligned memory, posix_memalign");
-    abort();
-  }
-
-  // We use mlock and memset here to make sure that the memory
-  // actually gets paged in and thus accounted for.
-  if (mlock(buffer, size) != 0) {
-    perror("Failed to lock memory, mlock");
-    abort();
-  }
-
-  if (memset(buffer, 1, size) != buffer) {
-    perror("Failed to fill memory, memset");
-    abort();
-  }
-
-  os::sleep(duration);
-
-  return 0;
-}
-
-
 TYPED_TEST(MemIsolatorTest, MemUsage)
 {
   slave::Flags flags;
@@ -721,87 +692,52 @@ TYPED_TEST(MemIsolatorTest, MemUsage)
   Try<Isolator*> isolator = TypeParam::create(flags);
   CHECK_SOME(isolator);
 
-  // A PosixLauncher is sufficient even when testing a cgroups isolator.
-  Try<Launcher*> launcher = PosixLauncher::create(flags);
-
   ExecutorInfo executorInfo;
   executorInfo.mutable_resources()->CopyFrom(
       Resources::parse("mem:1024").get());
 
   ContainerID containerId;
-  containerId.set_value("memory_usage");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
-
-  int pipes[2];
-  ASSERT_NE(-1, ::pipe(pipes));
-
-  Try<pid_t> pid = launcher.get()->fork(
+  AWAIT_READY(isolator.get()->prepare(
       containerId,
-      "/bin/sh",
-      vector<string>(),
-      Subprocess::FD(STDIN_FILENO),
-      Subprocess::FD(STDOUT_FILENO),
-      Subprocess::FD(STDERR_FILENO),
-      None(),
-      None(),
-      lambda::bind(&consumeMemory, Megabytes(256), Seconds(10), pipes));
-
-  ASSERT_SOME(pid);
-
-  // Set up the reaper to wait on the forked child.
-  Future<Option<int> > status = process::reap(pid.get());
-
-  // Continue in the parent.
-  ASSERT_SOME(os::close(pipes[0]));
+      executorInfo,
+      dir.get(),
+      None()));
 
-  // Isolate the forked child.
-  AWAIT_READY(isolator.get()->isolate(containerId, pid.get()));
+  MemoryTestHelper helper;
+  ASSERT_SOME(helper.spawn());
+  ASSERT_SOME(helper.pid());
 
-  // Now signal the child to continue.
-  char dummy;
-  ASSERT_LT(0, ::write(pipes[1], &dummy, sizeof(dummy)));
-
-  ASSERT_SOME(os::close(pipes[1]));
-
-  // Wait up to 5 seconds for the child process to consume 256 MB of memory;
-  ResourceStatistics statistics;
-  Bytes threshold = Megabytes(256);
-  Duration waited = Duration::zero();
-  do {
-    Future<ResourceStatistics> usage = isolator.get()->usage(containerId);
-    AWAIT_READY(usage);
+  // Set up the reaper to wait on the subprocess.
+  Future<Option<int>> status = process::reap(helper.pid().get());
 
-    statistics = usage.get();
+  // Isolate the subprocess.
+  AWAIT_READY(isolator.get()->isolate(containerId, helper.pid().get()));
 
-    // If we meet our usage expectations, we're done!
-    if (statistics.mem_rss_bytes() >= threshold.bytes()) {
-      break;
-    }
+  const Bytes allocation = Megabytes(128);
+  EXPECT_SOME(helper.increaseRSS(allocation));
 
-    os::sleep(Seconds(1));
-    waited += Seconds(1);
-  } while (waited < Seconds(5));
+  Future<ResourceStatistics> usage = isolator.get()->usage(containerId);
+  AWAIT_READY(usage);
 
-  EXPECT_LE(threshold.bytes(), statistics.mem_rss_bytes());
+  EXPECT_GE(usage.get().mem_rss_bytes(), allocation.bytes());
 
-  // Ensure all processes are killed.
-  AWAIT_READY(launcher.get()->destroy(containerId));
+  // Ensure the process is killed.
+  helper.cleanup();
 
-  // Make sure the child was reaped.
+  // Make sure the subprocess was reaped.
   AWAIT_READY(status);
 
   // Let the isolator clean up.
   AWAIT_READY(isolator.get()->cleanup(containerId));
 
   delete isolator.get();
-  delete launcher.get();
 }
 
 
@@ -822,15 +758,18 @@ TEST_F(PerfEventIsolatorTest, ROOT_CGROUPS_Sample)
   ExecutorInfo executorInfo;
 
   ContainerID containerId;
-  containerId.set_value("test");
+  containerId.set_value(UUID::random().toString());
 
   // Use a relative temporary directory so it gets cleaned up
   // automatically with the test.
   Try<string> dir = os::mkdtemp(path::join(os::getcwd(), "XXXXXX"));
   ASSERT_SOME(dir);
 
-  AWAIT_READY(
-      isolator.get()->prepare(containerId, executorInfo, dir.get(), None()));
+  AWAIT_READY(isolator.get()->prepare(
+      containerId,
+      executorInfo,
+      dir.get(),
+      None()));
 
   // This first sample is likely to be empty because perf hasn't
   // completed yet but we should still have the required fields.
@@ -916,7 +855,12 @@ TEST_F(SharedFilesystemIsolatorTest, ROOT_RelativeVolume)
   containerId.set_value(UUID::random().toString());
 
   Future<Option<CommandInfo> > prepare =
-    isolator.get()->prepare(containerId, executorInfo, flags.work_dir, None());
+    isolator.get()->prepare(
+        containerId,
+        executorInfo,
+        flags.work_dir,
+        None());
+
   AWAIT_READY(prepare);
   ASSERT_SOME(prepare.get());
 
@@ -1008,7 +952,12 @@ TEST_F(SharedFilesystemIsolatorTest, ROOT_AbsoluteVolume)
   containerId.set_value(UUID::random().toString());
 
   Future<Option<CommandInfo> > prepare =
-    isolator.get()->prepare(containerId, executorInfo, flags.work_dir, None());
+    isolator.get()->prepare(
+        containerId,
+        executorInfo,
+        flags.work_dir,
+        None());
+
   AWAIT_READY(prepare);
   ASSERT_SOME(prepare.get());
 
@@ -1071,7 +1020,7 @@ TEST_F(NamespacesPidIsolatorTest, ROOT_PidNamespace)
   ASSERT_SOME(containerizer);
 
   ContainerID containerId;
-  containerId.set_value("test_container");
+  containerId.set_value(UUID::random().toString());
 
   // Write the command's pid namespace inode and init name to files.
   const string command =
@@ -1168,13 +1117,13 @@ TYPED_TEST(UserCgroupIsolatorTest, ROOT_CGROUPS_UserCgroup)
       Resources::parse("mem:1024;cpus:1").get()); // For cpu/mem isolators.
 
   ContainerID containerId;
-  containerId.set_value("container");
+  containerId.set_value(UUID::random().toString());
 
   AWAIT_READY(isolator.get()->prepare(
-        containerId,
-        executorInfo,
-        os::getcwd(),
-        UNPRIVILEGED_USERNAME));
+      containerId,
+      executorInfo,
+      os::getcwd(),
+      UNPRIVILEGED_USERNAME));
 
   // Isolators don't provide a way to determine the cgroups they use
   // so we'll inspect the cgroups for an isolated dummy process.