You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by id...@apache.org on 2014/10/28 20:23:40 UTC
[4/8] git commit: Add getns() for namespaces.
Add getns() for namespaces.
Review: https://reviews.apache.org/r/27127
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/36505730
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/36505730
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/36505730
Branch: refs/heads/master
Commit: 36505730ac59d5255cd616618ce78e2ee88fca3d
Parents: 57447a7
Author: Ian Downes <id...@twitter.com>
Authored: Fri Oct 24 11:49:18 2014 -0700
Committer: Ian Downes <id...@twitter.com>
Committed: Tue Oct 28 12:04:16 2014 -0700
----------------------------------------------------------------------
src/linux/ns.hpp | 25 +++++++++++++++++++
src/tests/ns_tests.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/36505730/src/linux/ns.hpp
----------------------------------------------------------------------
diff --git a/src/linux/ns.hpp b/src/linux/ns.hpp
index 53c95a4..60adaa4 100644
--- a/src/linux/ns.hpp
+++ b/src/linux/ns.hpp
@@ -198,6 +198,31 @@ inline Try<Nothing> setns(pid_t pid, const std::string& ns)
return ns::setns(path, ns);
}
+
+// Get the inode number of the specified namespace for the specified
+// pid. The inode number identifies the namespace and can be used for
+// comparisons, i.e., two processes with the same inode for a given
+// namespace type are in the same namespace.
+inline Try<ino_t> getns(pid_t pid, const std::string& ns)
+{
+ if (!os::exists(pid)) {
+ return Error("Pid " + stringify(pid) + " does not exist");
+ }
+
+ if (ns::namespaces().count(ns) < 1) {
+ return Error("Namespace '" + ns + "' is not supported");
+ }
+
+ std::string path = path::join("/proc", stringify(pid), "ns", ns);
+ struct stat s;
+ if (::stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Failed to stat " + ns + " namespace handle"
+ " for pid " + stringify(pid));
+ }
+
+ return s.st_ino;
+}
+
} // namespace ns {
#endif // __LINUX_NS_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/36505730/src/tests/ns_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/ns_tests.cpp b/src/tests/ns_tests.cpp
index c4cf9ab..30218cf 100644
--- a/src/tests/ns_tests.cpp
+++ b/src/tests/ns_tests.cpp
@@ -154,3 +154,63 @@ TEST(NsTest, ROOT_setnsMultipleThreads)
EXPECT_EQ(0, pthread_cancel(pthread));
EXPECT_EQ(0, pthread_join(pthread, NULL));
}
+
+
+// Use a different child function for clone because it requires
+// int(*)(void*).
+static int childGetns(void* arg)
+{
+ // Sleep until killed.
+ while (true) { sleep(1); }
+
+ ABORT("Error, child should be killed before reaching here");
+}
+
+
+// Test that we can get the namespace inodes for a forked child.
+TEST(NsTest, ROOT_getns)
+{
+ set<string> namespaces = ns::namespaces();
+
+ // ns::setns() does not support "pid".
+ namespaces.erase("pid");
+
+ // Use the first other namespace available.
+ ASSERT_FALSE(namespaces.empty());
+ string ns = *(namespaces.begin());
+
+ ASSERT_SOME(ns::getns(::getpid(), ns));
+
+ Try<int> nstype = ns::nstype(ns);
+ ASSERT_SOME(nstype);
+
+ // 8 MiB stack for child.
+ static unsigned long long stack[(8*1024*1024)/sizeof(unsigned long long)];
+
+ pid_t pid = clone(
+ childGetns,
+ &stack[sizeof(stack)/sizeof(stack[0]) - 1], // Stack grows down.
+ SIGCHLD | nstype.get(),
+ NULL);
+
+ ASSERT_NE(-1, pid);
+
+ // Continue in parent.
+ Try<ino_t> nsParent = ns::getns(::getpid(), ns);
+ ASSERT_SOME(nsParent);
+
+ Try<ino_t> nsChild = ns::getns(pid, ns);
+ ASSERT_SOME(nsChild);
+
+ // Child should be in a different namespace.
+ EXPECT_NE(nsParent.get(), nsChild.get());
+
+ // Kill the child process.
+ ASSERT_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));
+}