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());
}