You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2016/03/26 13:56:45 UTC

[3/4] mesos git commit: LinuxLauncher: Used `parentHook` to implement freezer assignment.

LinuxLauncher: Used `parentHook` to implement freezer assignment.

Previously assigning the process to the freezer hierarchy basically
reimplemented the same blocking and error handling logic provided by
parentHooks.

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


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

Branch: refs/heads/master
Commit: a2cef18b8af739f63122b45690cdd6a996fd9912
Parents: 400ff4c
Author: Joerg Schad <jo...@mesosphere.io>
Authored: Sat Mar 26 12:20:09 2016 +0100
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Sat Mar 26 12:41:41 2016 +0100

----------------------------------------------------------------------
 .../containerizer/mesos/linux_launcher.cpp      | 134 ++++++++-----------
 1 file changed, 55 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/a2cef18b/src/slave/containerizer/mesos/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.cpp b/src/slave/containerizer/mesos/linux_launcher.cpp
index 9c80cfb..550c582 100644
--- a/src/slave/containerizer/mesos/linux_launcher.cpp
+++ b/src/slave/containerizer/mesos/linux_launcher.cpp
@@ -222,26 +222,8 @@ Future<hashset<ContainerID>> LinuxLauncher::recover(
 }
 
 
-static int childSetup(
-    int pipes[2],
-    const Option<lambda::function<int()>>& setup)
+static int childSetup(const Option<lambda::function<int()>>& setup)
 {
-  // In child.
-  ::close(pipes[1]);
-
-  // Do a blocking read on the pipe 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");
-  }
-
-  ::close(pipes[0]);
-
   // Move to a different session (and new process group) so we're
   // independent from the slave's session (otherwise children will
   // receive SIGHUP if the slave exits).
@@ -262,55 +244,85 @@ static int childSetup(
 }
 
 
-Try<pid_t> LinuxLauncher::fork(
-    const ContainerID& containerId,
-    const string& path,
-    const vector<string>& argv,
-    const process::Subprocess::IO& in,
-    const process::Subprocess::IO& out,
-    const process::Subprocess::IO& err,
-    const Option<flags::FlagsBase>& flags,
-    const Option<map<string, string>>& environment,
-    const Option<lambda::function<int()>>& setup,
-    const Option<int>& namespaces)
+// A hook that is executed in the parent process. It attempts to move a process
+// into the freezer cgroup.
+//
+// NOTE: The child process is blocked by the hook infrastructure while
+// these hooks are executed.
+// NOTE: Returning an Error implies the child process will be killed.
+Try<Nothing> assignFreezerHierarchy(
+    pid_t child,
+    const string& hierarchy,
+    const string& cgroup)
 {
   // Create a freezer cgroup for this container if necessary.
-  Try<bool> exists = cgroups::exists(freezerHierarchy, cgroup(containerId));
+  Try<bool> exists = cgroups::exists(hierarchy, cgroup);
   if (exists.isError()) {
-    return Error("Failed to check existence of freezer cgroup: " +
+    return Error("Failed to assign process to its freezer cgroup: "
+                 "Failed to check existence of freezer cgroup: " +
                  exists.error());
   }
 
   if (!exists.get()) {
-    Try<Nothing> created =
-      cgroups::create(freezerHierarchy, cgroup(containerId));
+    Try<Nothing> created = cgroups::create(hierarchy, cgroup);
 
     if (created.isError()) {
-      return Error("Failed to create freezer cgroup: " + created.error());
+      return Error("Failed to assign process to its freezer cgroup: "
+                   "Failed to create freezer cgroup: " + created.error());
     }
   }
 
-  // Use a pipe to block the child until it's been moved into the
-  // freezer cgroup.
-  int pipes[2];
+  // Move the child into the freezer cgroup. Any grandchildren will
+  // also be contained in the cgroup.
+  Try<Nothing> assign = cgroups::assign(hierarchy, cgroup, child);
+
+  if (assign.isError()) {
+    return Error("Failed to assign process to its freezer cgroup: " +
+                 assign.error());
+  }
+
+  return Nothing();
+}
 
-  // We assume this should not fail under reasonable conditions so we
-  // use CHECK.
-  CHECK_EQ(0, ::pipe(pipes));
 
+Try<pid_t> LinuxLauncher::fork(
+    const ContainerID& containerId,
+    const string& path,
+    const vector<string>& argv,
+    const process::Subprocess::IO& in,
+    const process::Subprocess::IO& out,
+    const process::Subprocess::IO& err,
+    const Option<flags::FlagsBase>& flags,
+    const Option<map<string, string>>& environment,
+    const Option<lambda::function<int()>>& setup,
+    const Option<int>& namespaces)
+{
   int cloneFlags = namespaces.isSome() ? namespaces.get() : 0;
   cloneFlags |= SIGCHLD; // Specify SIGCHLD as child termination signal.
 
   LOG(INFO) << "Cloning child process with flags = "
             << ns::stringify(cloneFlags);
 
+  // NOTE: The child process will be blocked until all hooks have been
+  // executed.
+  vector<Subprocess::Hook> parentHooks;
+
+  // NOTE: Currently we don't care about the order of the hooks, as
+  // both hooks are independent.
+
   // If we are on systemd, then extend the life of the child. As with the
   // freezer, any grandchildren will also be contained in the slice.
-  std::vector<Subprocess::Hook> parentHooks;
   if (systemdHierarchy.isSome()) {
     parentHooks.emplace_back(Subprocess::Hook(&systemd::mesos::extendLifetime));
   }
 
+  // Create parent Hook for moving child into freezer cgroup.
+  parentHooks.emplace_back(Subprocess::Hook(lambda::bind(
+      &assignFreezerHierarchy,
+      lambda::_1,
+      freezerHierarchy,
+      cgroup(containerId))));
+
   Try<Subprocess> child = subprocess(
       path,
       argv,
@@ -319,7 +331,7 @@ Try<pid_t> LinuxLauncher::fork(
       err,
       flags,
       environment,
-      lambda::bind(&childSetup, pipes, setup),
+      lambda::bind(&childSetup, setup),
       lambda::bind(&os::clone, lambda::_1, cloneFlags),
       parentHooks);
 
@@ -327,42 +339,6 @@ Try<pid_t> LinuxLauncher::fork(
     return Error("Failed to clone child process: " + child.error());
   }
 
-  // Parent.
-  os::close(pipes[0]);
-
-  // Move the child into the freezer cgroup. Any grandchildren will
-  // also be contained in the cgroup.
-  // TODO(jieyu): Move this logic to the subprocess (i.e.,
-  // mesos-containerizer launch).
-  Try<Nothing> assign = cgroups::assign(
-      freezerHierarchy,
-      cgroup(containerId),
-      child.get().pid());
-
-  if (assign.isError()) {
-    LOG(ERROR) << "Failed to assign process " << child.get().pid()
-                << " of container '" << containerId << "'"
-                << " to its freezer cgroup: " << assign.error();
-
-    ::kill(child.get().pid(), SIGKILL);
-    return Error("Failed to contain process");
-  }
-
-  // Now that we've contained the child we can signal it to continue
-  // by writing to the pipe.
-  char dummy;
-  ssize_t length;
-  while ((length = ::write(pipes[1], &dummy, sizeof(dummy))) == -1 &&
-         errno == EINTR);
-
-  os::close(pipes[1]);
-
-  if (length != sizeof(dummy)) {
-    // Ensure the child is killed.
-    ::kill(child.get().pid(), SIGKILL);
-    return Error("Failed to synchronize child process");
-  }
-
   if (!pids.contains(containerId)) {
     pids.put(containerId, child.get().pid());
   }