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 2016/12/05 05:42:33 UTC

[1/9] mesos git commit: Added an I/O switchboard test with TTY enabled.

Repository: mesos
Updated Branches:
  refs/heads/master 97696a06b -> 61e2dc1d8


Added an I/O switchboard test with TTY enabled.

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


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

Branch: refs/heads/master
Commit: 61e2dc1d8cf853179a2d423fedfc972653ea5db2
Parents: fd142a0
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 22:12:16 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 .../containerizer/io_switchboard_tests.cpp      | 88 ++++++++++++++++++--
 1 file changed, 83 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/61e2dc1d/src/tests/containerizer/io_switchboard_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/io_switchboard_tests.cpp b/src/tests/containerizer/io_switchboard_tests.cpp
index d2db61e..ebf9bc7 100644
--- a/src/tests/containerizer/io_switchboard_tests.cpp
+++ b/src/tests/containerizer/io_switchboard_tests.cpp
@@ -23,10 +23,12 @@
 
 #include <stout/json.hpp>
 #include <stout/os.hpp>
+#include <stout/path.hpp>
 #include <stout/protobuf.hpp>
 #include <stout/uuid.hpp>
 
 #include <mesos/http.hpp>
+#include <mesos/mesos.hpp>
 
 #include <mesos/agent/agent.hpp>
 
@@ -35,6 +37,7 @@
 
 #include "slave/containerizer/mesos/io/switchboard.hpp"
 
+#include "tests/environment.hpp"
 #include "tests/mesos.hpp"
 
 namespace http = process::http;
@@ -45,8 +48,13 @@ namespace unix = process::network::unix;
 
 using mesos::agent::Call;
 
-
+using mesos::internal::slave::Fetcher;
 using mesos::internal::slave::IOSwitchboardServer;
+using mesos::internal::slave::MesosContainerizer;
+
+using mesos::internal::slave::state::SlaveState;
+
+using mesos::slave::ContainerTermination;
 
 using process::Future;
 using process::Owned;
@@ -57,11 +65,11 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-class IOSwitchboardTest : public TemporaryDirectoryTest {};
+#ifndef __WINDOWS__
+class IOSwitchboardServerTest : public TemporaryDirectoryTest {};
 
 
-#ifndef __WINDOWS__
-TEST_F(IOSwitchboardTest, ServerRedirectLog)
+TEST_F(IOSwitchboardServerTest, ServerRedirectLog)
 {
   int stdoutPipe[2];
   int stderrPipe[2];
@@ -150,7 +158,7 @@ TEST_F(IOSwitchboardTest, ServerRedirectLog)
 }
 
 
-TEST_F(IOSwitchboardTest, ServerAttachOutput)
+TEST_F(IOSwitchboardServerTest, ServerAttachOutput)
 {
   Try<int> nullFd = os::open("/dev/null", O_RDWR);
   ASSERT_SOME(nullFd);
@@ -294,6 +302,76 @@ TEST_F(IOSwitchboardTest, ServerAttachOutput)
   EXPECT_EQ(data, stdoutReceived);
   EXPECT_EQ(data, stderrReceived);
 }
+
+
+class IOSwitchboardTest
+  : public ContainerizerTest<slave::MesosContainerizer> {};
+
+
+// The test verifies the output redirection of the container with TTY
+// allocated for the container.
+TEST_F(IOSwitchboardTest, OutputRedirectionWithTTY)
+{
+  slave::Flags flags = CreateSlaveFlags();
+  flags.launcher = "posix";
+  flags.isolation = "posix/cpu";
+  flags.io_switchboard_enable_server = true;
+
+  Fetcher fetcher;
+
+  Try<MesosContainerizer*> create = MesosContainerizer::create(
+      flags,
+      false,
+      &fetcher);
+
+  ASSERT_SOME(create);
+
+  Owned<MesosContainerizer> containerizer(create.get());
+
+  SlaveState state;
+  state.id = SlaveID();
+
+  AWAIT_READY(containerizer->recover(state));
+
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  Try<string> directory = environment->mkdtemp();
+  ASSERT_SOME(directory);
+
+  // Print 'Hello' to stdout and 'World' to stderr. Since the
+  // container requests a TTY. Both will be redirected to the same
+  // terminal device and logged in 'stdout' in the sandbox.
+  ExecutorInfo executorInfo = createExecutorInfo(
+      "executor",
+      "printf Hello; printf World 1>&2",
+      "cpus:1");
+
+  // Request a tty for the container.
+  executorInfo.mutable_container()->set_type(ContainerInfo::MESOS);
+  executorInfo.mutable_container()->mutable_tty_info();
+
+  Future<bool> launch = containerizer->launch(
+      containerId,
+      None(),
+      executorInfo,
+      directory.get(),
+      None(),
+      SlaveID(),
+      map<string, string>(),
+      true); // TODO(benh): Ever want to test not checkpointing?
+
+  AWAIT_ASSERT_TRUE(launch);
+
+  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);
+
+  AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
+  ASSERT_TRUE(wait.get()->has_status());
+  EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+  EXPECT_SOME_EQ("HelloWorld", os::read(path::join(directory.get(), "stdout")));
+}
 #endif // __WINDOWS__
 
 } // namespace tests {


[2/9] mesos git commit: Allowed subprocess to take duplicated FDs.

Posted by ji...@apache.org.
Allowed subprocess to take duplicated FDs.

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


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

Branch: refs/heads/master
Commit: c7f953aadcead297d8119e0c3564b8a2f67b518e
Parents: d6bc482
Author: Jie Yu <yu...@gmail.com>
Authored: Sat Dec 3 23:53:00 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 .../include/process/posix/subprocess.hpp        | 66 +++++++++++---------
 .../include/process/windows/subprocess.hpp      | 29 +++++----
 3rdparty/libprocess/src/subprocess.cpp          | 12 ++--
 3 files changed, 62 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f953aa/3rdparty/libprocess/include/process/posix/subprocess.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/posix/subprocess.hpp b/3rdparty/libprocess/include/process/posix/subprocess.hpp
index aa4609d..60f40ea 100644
--- a/3rdparty/libprocess/include/process/posix/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/posix/subprocess.hpp
@@ -27,6 +27,7 @@
 #include <stout/check.hpp>
 #include <stout/error.hpp>
 #include <stout/foreach.hpp>
+#include <stout/hashset.hpp>
 #include <stout/nothing.hpp>
 #include <stout/lambda.hpp>
 #include <stout/none.hpp>
@@ -70,6 +71,15 @@ inline pid_t defaultClone(const lambda::function<int()>& func)
 
 namespace internal {
 
+inline void close(const hashset<int>& fds)
+{
+  foreach (int fd, fds) {
+    if (fd >= 0) {
+      os::close(fd);
+    }
+  }
+}
+
 // This function will invoke `os::close` on all specified file
 // descriptors that are valid (i.e., not `None` and >= 0).
 inline void close(
@@ -77,17 +87,14 @@ inline void close(
     const OutputFileDescriptors& stdoutfds,
     const OutputFileDescriptors& stderrfds)
 {
-  int fds[6] = {
-    stdinfds.read, stdinfds.write.getOrElse(-1),
-    stdoutfds.read.getOrElse(-1), stdoutfds.write,
-    stderrfds.read.getOrElse(-1), stderrfds.write
-  };
-
-  foreach (int fd, fds) {
-    if (fd >= 0) {
-      os::close(fd);
-    }
-  }
+  close({
+    stdinfds.read,
+    stdinfds.write.getOrElse(-1),
+    stdoutfds.read.getOrElse(-1),
+    stdoutfds.write,
+    stderrfds.read.getOrElse(-1),
+    stderrfds.write
+  });
 }
 
 
@@ -98,10 +105,13 @@ inline Try<Nothing> cloexec(
     const OutputFileDescriptors& stdoutfds,
     const OutputFileDescriptors& stderrfds)
 {
-  int fds[6] = {
-    stdinfds.read, stdinfds.write.getOrElse(-1),
-    stdoutfds.read.getOrElse(-1), stdoutfds.write,
-    stderrfds.read.getOrElse(-1), stderrfds.write
+  hashset<int> fds = {
+    stdinfds.read,
+    stdinfds.write.getOrElse(-1),
+    stdoutfds.read.getOrElse(-1),
+    stdoutfds.write,
+    stderrfds.read.getOrElse(-1),
+    stderrfds.write
   };
 
   foreach (int fd, fds) {
@@ -167,6 +177,10 @@ inline int childMain(
   // parent has closed stdin/stdout/stderr when calling this
   // function (in that case, a dup'ed file descriptor may have the
   // same file descriptor number as stdin/stdout/stderr).
+  //
+  // We also need to ensure that we don't "double close" any file
+  // descriptors in the case where one of stdinfds.read,
+  // stdoutfds.write, or stdoutfds.write are equal.
   if (stdinfds.read != STDIN_FILENO &&
       stdinfds.read != STDOUT_FILENO &&
       stdinfds.read != STDERR_FILENO) {
@@ -174,12 +188,15 @@ inline int childMain(
   }
   if (stdoutfds.write != STDIN_FILENO &&
       stdoutfds.write != STDOUT_FILENO &&
-      stdoutfds.write != STDERR_FILENO) {
+      stdoutfds.write != STDERR_FILENO &&
+      stdoutfds.write != stdinfds.read) {
     ::close(stdoutfds.write);
   }
   if (stderrfds.write != STDIN_FILENO &&
       stderrfds.write != STDOUT_FILENO &&
-      stderrfds.write != STDERR_FILENO) {
+      stderrfds.write != STDERR_FILENO &&
+      stderrfds.write != stdinfds.read &&
+      stderrfds.write != stdoutfds.write) {
     ::close(stderrfds.write);
   }
 
@@ -313,6 +330,10 @@ inline Try<pid_t> cloneChild(
     return error;
   }
 
+  // Close the child-ends of the file descriptors that are created by
+  // this function.
+  internal::close({stdinfds.read, stdoutfds.write, stderrfds.write});
+
   if (blocking) {
     os::close(pipes[0]);
 
@@ -329,12 +350,6 @@ inline Try<pid_t> cloneChild(
 
         os::close(pipes[1]);
 
-        // Close the child-ends of the file descriptors that are created
-        // by this function.
-        os::close(stdinfds.read);
-        os::close(stdoutfds.write);
-        os::close(stderrfds.write);
-
         // Ensure the child is killed.
         ::kill(pid, SIGKILL);
 
@@ -357,11 +372,6 @@ inline Try<pid_t> cloneChild(
       // Ensure the child is killed.
       ::kill(pid, SIGKILL);
 
-      // Close the child-ends of the file descriptors that are created
-      // by this function.
-      os::close(stdinfds.read);
-      os::close(stdoutfds.write);
-      os::close(stderrfds.write);
       return Error("Failed to synchronize child process");
     }
   }

http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f953aa/3rdparty/libprocess/include/process/windows/subprocess.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/windows/subprocess.hpp b/3rdparty/libprocess/include/process/windows/subprocess.hpp
index f452f67..e2ba752 100644
--- a/3rdparty/libprocess/include/process/windows/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/windows/subprocess.hpp
@@ -23,6 +23,7 @@
 
 #include <stout/error.hpp>
 #include <stout/foreach.hpp>
+#include <stout/hashset.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
 #include <stout/try.hpp>
@@ -44,6 +45,15 @@ using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;
 
 namespace internal {
 
+inline void close(const hashset<HANDLE>& fds)
+{
+  foreach (HANDLE fd, fds) {
+    if (fd != INVALID_HANDLE_VALUE) {
+      os::close(fd);
+    }
+  }
+}
+
 // This function will invoke `os::close` on all specified file
 // descriptors that are valid (i.e., not `None` and >= 0).
 inline void close(
@@ -51,17 +61,14 @@ inline void close(
     const OutputFileDescriptors& stdoutfds,
     const OutputFileDescriptors& stderrfds)
 {
-  HANDLE fds[6] = {
-    stdinfds.read, stdinfds.write.getOrElse(INVALID_HANDLE_VALUE),
-    stdoutfds.read.getOrElse(INVALID_HANDLE_VALUE), stdoutfds.write,
-    stderrfds.read.getOrElse(INVALID_HANDLE_VALUE), stderrfds.write
-  };
-
-  foreach (HANDLE fd, fds) {
-    if (fd != INVALID_HANDLE_VALUE) {
-      os::close(fd);
-    }
-  }
+  close({
+    stdinfds.read,
+    stdinfds.write.getOrElse(INVALID_HANDLE_VALUE),
+    stdoutfds.read.getOrElse(INVALID_HANDLE_VALUE),
+    stdoutfds.write,
+    stderrfds.read.getOrElse(INVALID_HANDLE_VALUE),
+    stderrfds.write
+  });
 }
 
 // Retrieves system environment in a `std::map`, ignoring

http://git-wip-us.apache.org/repos/asf/mesos/blob/c7f953aa/3rdparty/libprocess/src/subprocess.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess.cpp b/3rdparty/libprocess/src/subprocess.cpp
index b3efb9c..340fc32 100644
--- a/3rdparty/libprocess/src/subprocess.cpp
+++ b/3rdparty/libprocess/src/subprocess.cpp
@@ -327,17 +327,17 @@ Try<Subprocess> subprocess(
       return error;
     }
 
+    // Close the child-ends of the file descriptors that are created
+    // by this function.
+    // TODO(jieyu): We should move the closing of FDs to
+    // 'createChildProcess' to be consistent with the posix path.
+    internal::close({stdinfds.read, stdoutfds.write, stderrfds.write});
+
     process.data->processInformation = processInformation.get();
     process.data->pid = processInformation.get().dwProcessId;
 #endif // __WINDOWS__
   }
 
-  // Close the child-ends of the file descriptors that are created
-  // by this function.
-  os::close(stdinfds.read);
-  os::close(stdoutfds.write);
-  os::close(stderrfds.write);
-
   // For any pipes, store the parent side of the pipe so that
   // the user can communicate with the subprocess.
   process.data->in = stdinfds.write;


[4/9] mesos git commit: Added a check to require I/O switchboard server for TTY support.

Posted by ji...@apache.org.
Added a check to require I/O switchboard server for TTY support.

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


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

Branch: refs/heads/master
Commit: a43d57b6b54d152fd38733b666dd4b4a0cf25f95
Parents: 97696a0
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 13:42:11 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 src/slave/containerizer/mesos/io/switchboard.cpp | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/a43d57b6/src/slave/containerizer/mesos/io/switchboard.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard.cpp b/src/slave/containerizer/mesos/io/switchboard.cpp
index 778367a..2362f1b 100644
--- a/src/slave/containerizer/mesos/io/switchboard.cpp
+++ b/src/slave/containerizer/mesos/io/switchboard.cpp
@@ -171,6 +171,13 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
 #endif
 
   if (!flags.io_switchboard_enable_server) {
+    // TTY support requires I/O switchboard server so that stdio can
+    // be properly redirected to logger.
+    if (containerConfig.has_container_info() &&
+        containerConfig.container_info().has_tty_info()) {
+      return Failure("TTY support requires I/O switchboard server");
+    }
+
     ContainerLaunchInfo launchInfo;
 
     ContainerIO* out = launchInfo.mutable_out();


[8/9] mesos git commit: Supported TTY in I/O switchboard.

Posted by ji...@apache.org.
Supported TTY in I/O switchboard.

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


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

Branch: refs/heads/master
Commit: fd142a0d7b7ec27fdcffc3d679db46edc9432de3
Parents: c7f953a
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 18:16:06 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 include/mesos/slave/containerizer.proto         |   3 +
 src/slave/containerizer/mesos/containerizer.cpp |   5 +
 .../containerizer/mesos/io/switchboard.cpp      | 280 ++++++++++++++-----
 .../containerizer/mesos/io/switchboard.hpp      |  31 +-
 .../containerizer/mesos/io/switchboard_main.cpp |   1 +
 src/slave/containerizer/mesos/launch.cpp        |  10 +
 .../containerizer/io_switchboard_tests.cpp      |   2 +
 7 files changed, 251 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/include/mesos/slave/containerizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/slave/containerizer.proto b/include/mesos/slave/containerizer.proto
index 33b4c23..c70d437 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -212,6 +212,9 @@ message ContainerLaunchInfo {
   optional ContainerIO in = 11;
   optional ContainerIO out = 12;
   optional ContainerIO err = 13;
+
+  // (POSIX only) The slave path of the pseudo terminal.
+  optional string tty_slave_path = 14;
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index a7e2665..13cf757 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -1272,6 +1272,11 @@ Future<bool> MesosContainerizerProcess::_launch(
       return Failure("Multiple isolators specify stderr");
     }
 
+    if (isolatorLaunchInfo->has_tty_slave_path() &&
+        launchInfo.has_tty_slave_path()) {
+      return Failure("Multiple isolators specify tty");
+    }
+
     launchInfo.MergeFrom(isolatorLaunchInfo.get());
   }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/slave/containerizer/mesos/io/switchboard.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard.cpp b/src/slave/containerizer/mesos/io/switchboard.cpp
index 2362f1b..d5211b9 100644
--- a/src/slave/containerizer/mesos/io/switchboard.cpp
+++ b/src/slave/containerizer/mesos/io/switchboard.cpp
@@ -14,6 +14,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <stdio.h>
+#include <stdlib.h>
+
 #include <list>
 #include <map>
 #include <string>
@@ -38,6 +41,10 @@
 #include <stout/path.hpp>
 #include <stout/recordio.hpp>
 
+#ifndef __WINDOWS__
+#include <stout/posix/os.hpp>
+#endif // __WINDOWS__
+
 #include <mesos/http.hpp>
 #include <mesos/type_utils.hpp>
 
@@ -64,6 +71,7 @@ namespace unix = process::network::unix;
 
 using std::string;
 
+using process::ErrnoFailure;
 using process::Failure;
 using process::Future;
 using process::Owned;
@@ -170,11 +178,13 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
   }
 #endif
 
+  bool hasTTY = containerConfig.has_container_info() &&
+                containerConfig.container_info().has_tty_info();
+
   if (!flags.io_switchboard_enable_server) {
     // TTY support requires I/O switchboard server so that stdio can
     // be properly redirected to logger.
-    if (containerConfig.has_container_info() &&
-        containerConfig.container_info().has_tty_info()) {
+    if (hasTTY) {
       return Failure("TTY support requires I/O switchboard server");
     }
 
@@ -220,78 +230,175 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
                    " '" + stringify(containerId) + "'");
   }
 
+  // Return the set of fds that should be sent to the
+  // container and dup'd onto its stdin/stdout/stderr.
+  ContainerLaunchInfo launchInfo;
+
   // Manually construct pipes instead of using `Subprocess::PIPE`
   // so that the ownership of the FDs is properly represented. The
   // `Subprocess` spawned below owns one end of each pipe and will
   // be solely responsible for closing that end. The ownership of
   // the other end will be passed to the caller of this function
   // and eventually passed to the container being launched.
-  int infds[2];
-  int outfds[2];
-  int errfds[2];
+  int stdinToFd = -1;
+  int stdoutFromFd = -1;
+  int stderrFromFd = -1;
 
   // A list of file decriptors we've opened so far.
-  vector<int> fds = {};
+  hashset<int> openedFds = {};
+
+  // A list of file descriptors that will be passed to the I/O
+  // switchboard. We need to close those file descriptors once the
+  // I/O switchboard server is forked.
+  hashset<int> ioSwitchboardFds = {};
 
-  // Helper for closing the list of file
-  // descriptors we've opened so far.
-  auto close = [](const vector<int>& fds) {
+  // Helper for closing a set of file descriptors.
+  auto close = [](const hashset<int>& fds) {
     foreach (int fd, fds) {
       os::close(fd);
     }
   };
 
-  Try<Nothing> pipe = os::pipe(infds);
-  if (pipe.isError()) {
-    close(fds);
-    return Failure("Failed to create stdin pipe: " + pipe.error());
-  }
+  // Setup a pseudo terminal for the container.
+  if (hasTTY) {
+    // TODO(jieyu): Consider moving all TTY related method to stout.
+    // For instance, 'stout/posix/tty.hpp'.
 
-  fds.push_back(infds[0]);
-  fds.push_back(infds[1]);
+    // Set flag 'O_NOCTTY' so that the terminal device will not become
+    // the controlling terminal for the process.
+    int master = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC);
+    if (master == -1) {
+      return Failure("Failed to open a master pseudo terminal");
+    }
 
-  pipe = os::pipe(outfds);
-  if (pipe.isError()) {
-    close(fds);
-    return Failure("Failed to create stdout pipe: " + pipe.error());
-  }
+    openedFds.insert(master);
 
-  fds.push_back(outfds[0]);
-  fds.push_back(outfds[1]);
+    Try<string> slavePath = os::ptsname(master);
+    if (slavePath.isError()) {
+      close(openedFds);
+      return Failure("Failed to get the slave pseudo terminal path: " +
+                     slavePath.error());
+    }
 
-  pipe = os::pipe(errfds);
-  if (pipe.isError()) {
-    close(fds);
-    return Failure("Failed to create stderr pipe: " + pipe.error());
-  }
+    // Unlock the slave end of the pseudo terminal.
+    if (unlockpt(master) != 0) {
+      close(openedFds);
+      return ErrnoFailure("Failed to unlock the slave pseudo terminal");
+    }
+
+    // Set proper permission and ownership for the device.
+    if (grantpt(master) != 0) {
+      close(openedFds);
+      return ErrnoFailure("Failed to grant the slave pseudo terminal");
+    }
 
-  fds.push_back(errfds[0]);
-  fds.push_back(errfds[1]);
+    if (containerConfig.has_user()) {
+      Try<Nothing> chown = os::chown(
+          containerConfig.user(),
+          slavePath.get(),
+          false);
 
-  Try<Nothing> cloexec = os::cloexec(infds[0]);
-  if (cloexec.isError()) {
-    close(fds);
-    return Failure("Failed to cloexec infds.read: " + cloexec.error());
-  }
+      if (chown.isError()) {
+        close(openedFds);
+        return Failure("Failed to chown the slave pseudo terminal: " +
+                       chown.error());
+      }
+    }
+
+    // Open the slave end of the pseudo terminal. The opened file
+    // descriptor will be dup'ed to stdin/out/err of the container.
+    Try<int> slave = os::open(slavePath.get(), O_RDWR | O_NOCTTY | O_CLOEXEC);
+    if (slave.isError()) {
+      return Failure("Failed to open the slave pseudo terminal: " +
+                     slave.error());
+    }
 
-  cloexec = os::cloexec(outfds[1]);
-  if (cloexec.isError()) {
-    close(fds);
-    return Failure("Failed to cloexec outfds.write: " + cloexec.error());
+    openedFds.insert(slave.get());
+
+    LOG(INFO) << "Allocated pseudo terminal '" << slavePath.get()
+              << "' for container " << containerId;
+
+    stdinToFd = master;
+    stdoutFromFd = master;
+    stderrFromFd = master;
+
+    launchInfo.mutable_in()->set_type(ContainerIO::FD);
+    launchInfo.mutable_in()->set_fd(slave.get());
+
+    launchInfo.mutable_out()->set_type(ContainerIO::FD);
+    launchInfo.mutable_out()->set_fd(slave.get());
+
+    launchInfo.mutable_err()->set_type(ContainerIO::FD);
+    launchInfo.mutable_err()->set_fd(slave.get());
+
+    launchInfo.set_tty_slave_path(slavePath.get());
+  } else {
+    int infds[2];
+    int outfds[2];
+    int errfds[2];
+
+    Try<Nothing> pipe = os::pipe(infds);
+    if (pipe.isError()) {
+      close(openedFds);
+      return Failure("Failed to create stdin pipe: " + pipe.error());
+    }
+
+    openedFds.insert(infds[0]);
+    openedFds.insert(infds[1]);
+
+    pipe = os::pipe(outfds);
+    if (pipe.isError()) {
+      close(openedFds);
+      return Failure("Failed to create stdout pipe: " + pipe.error());
+    }
+
+    openedFds.insert(outfds[0]);
+    openedFds.insert(outfds[1]);
+
+    pipe = os::pipe(errfds);
+    if (pipe.isError()) {
+      close(openedFds);
+      return Failure("Failed to create stderr pipe: " + pipe.error());
+    }
+
+    openedFds.insert(errfds[0]);
+    openedFds.insert(errfds[1]);
+
+    stdinToFd = infds[1];
+    stdoutFromFd = outfds[0];
+    stderrFromFd = errfds[0];
+
+    launchInfo.mutable_in()->set_type(ContainerIO::FD);
+    launchInfo.mutable_in()->set_fd(infds[0]);
+
+    launchInfo.mutable_out()->set_type(ContainerIO::FD);
+    launchInfo.mutable_out()->set_fd(outfds[1]);
+
+    launchInfo.mutable_err()->set_type(ContainerIO::FD);
+    launchInfo.mutable_err()->set_fd(errfds[1]);
   }
 
-  cloexec = os::cloexec(errfds[1]);
-  if (cloexec.isError()) {
-    close(fds);
-    return Failure("Failed to cloexec errfds.write: " + cloexec.error());
+  // Make sure all file descriptors opened have CLOEXEC set.
+  foreach (int fd, openedFds) {
+    Try<Nothing> cloexec = os::cloexec(fd);
+    if (cloexec.isError()) {
+      close(openedFds);
+      return Failure("Failed to set cloexec: " + cloexec.error());
+    }
   }
 
+  ioSwitchboardFds.insert(stdinToFd);
+  ioSwitchboardFds.insert(stdoutFromFd);
+  ioSwitchboardFds.insert(stderrFromFd);
+
   // Set up our flags to send to the io switchboard server process.
   IOSwitchboardServerFlags switchboardFlags;
-  switchboardFlags.stdin_to_fd = infds[1];
-  switchboardFlags.stdout_from_fd = outfds[0];
+  switchboardFlags.tty = hasTTY;
+
+  // We use the default values for other file descriptor flags. Since
+  // I/O switchboard server's stdout and stderr will be redirected to
+  // the logger, we explicitly set the flags here.
   switchboardFlags.stdout_to_fd = STDOUT_FILENO;
-  switchboardFlags.stderr_from_fd = errfds[0];
   switchboardFlags.stderr_to_fd = STDERR_FILENO;
 
   if (containerConfig.container_class() == ContainerClass::DEBUG) {
@@ -321,17 +428,30 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
       map<string, string>(),
       None(),
       {},
-      {Subprocess::ChildHook::SETSID()});
+      {Subprocess::ChildHook::SETSID(),
+       Subprocess::ChildHook::DUP2(
+           stdinToFd,
+           IOSwitchboardServer::STDIN_TO_FD),
+       Subprocess::ChildHook::DUP2(
+           stdoutFromFd,
+           IOSwitchboardServer::STDOUT_FROM_FD),
+       Subprocess::ChildHook::DUP2(
+           stderrFromFd,
+           IOSwitchboardServer::STDERR_FROM_FD)});
 
   if (child.isError()) {
-    close(fds);
+    close(openedFds);
     return Failure("Failed to create io switchboard"
                    " server process: " + child.error());
   }
 
-  os::close(infds[1]);
-  os::close(outfds[0]);
-  os::close(errfds[0]);
+  close(ioSwitchboardFds);
+
+  // We remove the already closed file descriptors from 'openedFds' so
+  // that we don't close multiple times if failures happen below.
+  foreach (int fd, ioSwitchboardFds) {
+    openedFds.erase(fd);
+  }
 
   // Now that the child has come up, we checkpoint the socket
   // address we told it to bind to so we can access it later.
@@ -343,7 +463,7 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
       path, switchboardFlags.socket_path);
 
   if (checkpointed.isError()) {
-    close(fds);
+    close(openedFds);
     return Failure("Failed to checkpoint container's socket path to"
                    " '" + path + "': " + checkpointed.error());
   }
@@ -353,19 +473,6 @@ Future<Option<ContainerLaunchInfo>> IOSwitchboard::_prepare(
     child->pid(),
     process::reap(child->pid())));
 
-  // Return the set of fds that should be sent to the
-  // container and dup'd onto its stdin/stdout/stderr.
-  ContainerLaunchInfo launchInfo;
-
-  launchInfo.mutable_in()->set_type(ContainerIO::FD);
-  launchInfo.mutable_in()->set_fd(infds[0]);
-
-  launchInfo.mutable_out()->set_type(ContainerIO::FD);
-  launchInfo.mutable_out()->set_fd(outfds[1]);
-
-  launchInfo.mutable_err()->set_type(ContainerIO::FD);
-  launchInfo.mutable_err()->set_fd(errfds[1]);
-
   return launchInfo;
 #endif // __WINDOWS__
 }
@@ -435,13 +542,19 @@ Future<Nothing> IOSwitchboard::cleanup(
 
 
 #ifndef __WINDOWS__
-constexpr char IOSwitchboardServer::NAME[];
+const char IOSwitchboardServer::NAME[]          = "mesos-io-switchboard";
+const int  IOSwitchboardServer::STDIN_TO_FD     = STDERR_FILENO + 1;
+const int  IOSwitchboardServer::STDOUT_FROM_FD  = STDERR_FILENO + 2;
+const int  IOSwitchboardServer::STDERR_FROM_FD  = STDERR_FILENO + 3;
+const int  IOSwitchboardServer::STDOUT_TO_FD    = STDERR_FILENO + 4;
+const int  IOSwitchboardServer::STDERR_TO_FD    = STDERR_FILENO + 5;
 
 
 class IOSwitchboardServerProcess : public Process<IOSwitchboardServerProcess>
 {
 public:
   IOSwitchboardServerProcess(
+      bool _tty,
       int _stdinToFd,
       int _stdoutFromFd,
       int _stdoutToFd,
@@ -507,6 +620,7 @@ private:
       const string& data,
       const agent::ProcessIO::Data::Type& type);
 
+  bool tty;
   int stdinToFd;
   int stdoutFromFd;
   int stdoutToFd;
@@ -524,6 +638,7 @@ private:
 
 
 Try<Owned<IOSwitchboardServer>> IOSwitchboardServer::create(
+    bool tty,
     int stdinToFd,
     int stdoutFromFd,
     int stdoutToFd,
@@ -556,6 +671,7 @@ Try<Owned<IOSwitchboardServer>> IOSwitchboardServer::create(
   }
 
   return new IOSwitchboardServer(
+      tty,
       stdinToFd,
       stdoutFromFd,
       stdoutToFd,
@@ -567,6 +683,7 @@ Try<Owned<IOSwitchboardServer>> IOSwitchboardServer::create(
 
 
 IOSwitchboardServer::IOSwitchboardServer(
+    bool tty,
     int stdinToFd,
     int stdoutFromFd,
     int stdoutToFd,
@@ -575,6 +692,7 @@ IOSwitchboardServer::IOSwitchboardServer(
     const unix::Socket& socket,
     bool waitForConnection)
   : process(new IOSwitchboardServerProcess(
+        tty,
         stdinToFd,
         stdoutFromFd,
         stdoutToFd,
@@ -601,6 +719,7 @@ Future<Nothing> IOSwitchboardServer::run()
 
 
 IOSwitchboardServerProcess::IOSwitchboardServerProcess(
+    bool _tty,
     int _stdinToFd,
     int _stdoutFromFd,
     int _stdoutToFd,
@@ -608,7 +727,8 @@ IOSwitchboardServerProcess::IOSwitchboardServerProcess(
     int _stderrToFd,
     const unix::Socket& _socket,
     bool _waitForConnection)
-  : stdinToFd(_stdinToFd),
+  : tty(_tty),
+    stdinToFd(_stdinToFd),
     stdoutFromFd(_stdoutFromFd),
     stdoutToFd(_stdoutToFd),
     stderrFromFd(_stderrFromFd),
@@ -638,14 +758,24 @@ Future<Nothing> IOSwitchboardServerProcess::run()
                  lambda::_1,
                  agent::ProcessIO::Data::STDOUT)});
 
-      Future<Nothing> stderrRedirect = process::io::redirect(
-          stderrFromFd,
-          stderrToFd,
-          4096,
-          {defer(self(),
-                 &Self::outputHook,
-                 lambda::_1,
-                 agent::ProcessIO::Data::STDERR)});
+      // NOTE: We don't need to redirect stderr if TTY is enabled. If
+      // TTY is enabled for the container, stdout and stderr for the
+      // container will be redirected to the slave end of the pseudo
+      // terminal device. Both stdout and stderr of the container will
+      // both coming out from the master end of the pseudo terminal.
+      Future<Nothing> stderrRedirect;
+      if (tty) {
+        stderrRedirect = Nothing();
+      } else {
+        stderrRedirect = process::io::redirect(
+            stderrFromFd,
+            stderrToFd,
+            4096,
+            {defer(self(),
+                   &Self::outputHook,
+                   lambda::_1,
+                   agent::ProcessIO::Data::STDERR)});
+      }
 
       // Set the future once our IO redirects finish. On failure,
       // fail the future.

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/slave/containerizer/mesos/io/switchboard.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard.hpp b/src/slave/containerizer/mesos/io/switchboard.hpp
index 23c66bb..839665a 100644
--- a/src/slave/containerizer/mesos/io/switchboard.hpp
+++ b/src/slave/containerizer/mesos/io/switchboard.hpp
@@ -113,9 +113,17 @@ class IOSwitchboardServerProcess;
 class IOSwitchboardServer
 {
 public:
-  static constexpr char NAME[] = "mesos-io-switchboard";
+  static const char NAME[];
+
+  // Constant FD numbers used by I/O switchboard server.
+  static const int STDIN_TO_FD;
+  static const int STDOUT_FROM_FD;
+  static const int STDERR_FROM_FD;
+  static const int STDOUT_TO_FD;
+  static const int STDERR_TO_FD;
 
   static Try<process::Owned<IOSwitchboardServer>> create(
+      bool tty,
       int stdinToFd,
       int stdoutFromFd,
       int stdoutToFd,
@@ -130,6 +138,7 @@ public:
 
 private:
   IOSwitchboardServer(
+      bool tty,
       int stdinToFd,
       int stdoutFromFd,
       int stdoutToFd,
@@ -164,27 +173,36 @@ struct IOSwitchboardServerFlags : public virtual flags::FlagsBase
       "well as launch arbitrary subcommands inside a container and attach to\n"
       "its stdin/stdout/stderr.\n");
 
+    add(&IOSwitchboardServerFlags::tty,
+        "tty",
+        "If a pseudo terminal has been allocated for the container.");
+
     add(&IOSwitchboardServerFlags::stdin_to_fd,
         "stdin_to_fd",
-        "The file descriptor where incoming stdin data should be written.");
+        "The file descriptor where incoming stdin data should be written.",
+        IOSwitchboardServer::STDIN_TO_FD);
 
     add(&IOSwitchboardServerFlags::stdout_from_fd,
         "stdout_from_fd",
-        "The file descriptor that should be read to consume stdout data.");
+        "The file descriptor that should be read to consume stdout data.",
+        IOSwitchboardServer::STDOUT_FROM_FD);
 
     add(&IOSwitchboardServerFlags::stdout_to_fd,
         "stdout_to_fd",
         "A file descriptor where data read from\n"
-        "'stdout_from_fd' should be redirected to.");
+        "'stdout_from_fd' should be redirected to.",
+        IOSwitchboardServer::STDOUT_TO_FD);
 
     add(&IOSwitchboardServerFlags::stderr_from_fd,
         "stderr_from_fd",
-        "The file descriptor that should be read to consume stderr data.");
+        "The file descriptor that should be read to consume stderr data.",
+        IOSwitchboardServer::STDERR_FROM_FD);
 
     add(&IOSwitchboardServerFlags::stderr_to_fd,
         "stderr_to_fd",
         "A file descriptor where data read from\n"
-        "'stderr_from_fd' should be redirected to.");
+        "'stderr_from_fd' should be redirected to.",
+        IOSwitchboardServer::STDERR_TO_FD);
 
     add(&IOSwitchboardServerFlags::wait_for_connection,
         "wait_for_connection",
@@ -197,6 +215,7 @@ struct IOSwitchboardServerFlags : public virtual flags::FlagsBase
         "io switchboard should attach itself to.");
   }
 
+  bool tty;
   int stdin_to_fd;
   int stdout_from_fd;
   int stdout_to_fd;

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/slave/containerizer/mesos/io/switchboard_main.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/io/switchboard_main.cpp b/src/slave/containerizer/mesos/io/switchboard_main.cpp
index 5800217..aff6c21 100644
--- a/src/slave/containerizer/mesos/io/switchboard_main.cpp
+++ b/src/slave/containerizer/mesos/io/switchboard_main.cpp
@@ -38,6 +38,7 @@ int main(int argc, char** argv)
   }
 
   Try<Owned<IOSwitchboardServer>> server = IOSwitchboardServer::create(
+      flags.tty,
       flags.stdin_to_fd,
       flags.stdout_from_fd,
       flags.stdout_to_fd,

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index d78ca4d..f90fce2 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -356,6 +356,16 @@ int MesosContainerizerLaunch::execute()
     }
   }
 
+#ifndef __WINDOWS__
+  if (launchInfo.has_tty_slave_path()) {
+    Try<Nothing> setctty = os::setctty(STDIN_FILENO);
+    if (setctty.isError()) {
+      cerr << "Failed to set control tty: " << setctty.error() << endl;
+      exitWithStatus(EXIT_FAILURE);
+    }
+  }
+#endif // __WINDOWS__
+
 #ifdef __linux__
   if (flags.namespace_mnt_target.isSome()) {
     string path = path::join(

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd142a0d/src/tests/containerizer/io_switchboard_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/io_switchboard_tests.cpp b/src/tests/containerizer/io_switchboard_tests.cpp
index d82f22b..d2db61e 100644
--- a/src/tests/containerizer/io_switchboard_tests.cpp
+++ b/src/tests/containerizer/io_switchboard_tests.cpp
@@ -96,6 +96,7 @@ TEST_F(IOSwitchboardTest, ServerRedirectLog)
       "mesos-io-switchboard-" + UUID::random().toString());
 
   Try<Owned<IOSwitchboardServer>> server = IOSwitchboardServer::create(
+      false,
       nullFd.get(),
       stdoutPipe[0],
       stdoutFd.get(),
@@ -203,6 +204,7 @@ TEST_F(IOSwitchboardTest, ServerAttachOutput)
       "mesos-io-switchboard-" + UUID::random().toString());
 
   Try<Owned<IOSwitchboardServer>> server = IOSwitchboardServer::create(
+      false,
       nullFd.get(),
       stdoutFd.get(),
       nullFd.get(),


[7/9] mesos git commit: Added os::dup2 to stout.

Posted by ji...@apache.org.
Added os::dup2 to stout.

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


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

Branch: refs/heads/master
Commit: f0350822dbfa8ee599a4748b79887b46bab11eac
Parents: 9248867
Author: Jie Yu <yu...@gmail.com>
Authored: Sat Dec 3 11:22:24 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/posix/os.hpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/f0350822/3rdparty/stout/include/stout/posix/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/stout/include/stout/posix/os.hpp
index a8f7108..09196be 100644
--- a/3rdparty/stout/include/stout/posix/os.hpp
+++ b/3rdparty/stout/include/stout/posix/os.hpp
@@ -475,6 +475,19 @@ inline Try<Nothing> pipe(int pipe_fd[2])
 }
 
 
+inline Try<Nothing> dup2(int oldFd, int newFd)
+{
+  while (::dup2(oldFd, newFd) == -1) {
+    if (errno == EINTR) {
+      continue;
+    } else {
+      return ErrnoError();
+    }
+  }
+  return Nothing();
+}
+
+
 inline Try<std::string> ptsname(int master)
 {
   // 'ptsname' is not thread safe. Therefore, we use mutex here to


[3/9] mesos git commit: Added os::ptsname to stout.

Posted by ji...@apache.org.
Added os::ptsname to stout.

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


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

Branch: refs/heads/master
Commit: 5ee6f4f3ff2ad2e10cd2b3430f20c883b2f5b384
Parents: 4df544f
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 17:13:09 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/posix/os.hpp | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5ee6f4f3/3rdparty/stout/include/stout/posix/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/stout/include/stout/posix/os.hpp
index c37e64d..72e69a00 100644
--- a/3rdparty/stout/include/stout/posix/os.hpp
+++ b/3rdparty/stout/include/stout/posix/os.hpp
@@ -45,10 +45,13 @@
 
 #include <list>
 #include <map>
+#include <mutex>
 #include <set>
 #include <string>
 #include <vector>
 
+#include <stout/synchronized.hpp>
+
 #include <stout/os/close.hpp>
 #include <stout/os/environment.hpp>
 #include <stout/os/fcntl.hpp>
@@ -469,6 +472,23 @@ inline Try<Nothing> pipe(int pipe_fd[2])
   return Nothing();
 }
 
+
+inline Try<std::string> ptsname(int master)
+{
+  // 'ptsname' is not thread safe. Therefore, we use mutex here to
+  // make this method thread safe.
+  // TODO(jieyu): Consider using ptsname_r for linux.
+  static std::mutex* mutex = new std::mutex;
+
+  synchronized (mutex) {
+    const char* slavePath = ::ptsname(master);
+    if (slavePath == nullptr) {
+      return ErrnoError();
+    }
+    return slavePath;
+  }
+}
+
 } // namespace os {
 
 #endif // __STOUT_POSIX_OS_HPP__


[6/9] mesos git commit: Added a ErrnoFailure similar to ErrnoError.

Posted by ji...@apache.org.
Added a ErrnoFailure similar to ErrnoError.

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


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

Branch: refs/heads/master
Commit: 4df544f794b6df36017310b69ce72ed9a181bdaa
Parents: a43d57b
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 17:12:57 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/future.hpp | 30 +++++++++++++++++++++
 1 file changed, 30 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/4df544f7/3rdparty/libprocess/include/process/future.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/future.hpp b/3rdparty/libprocess/include/process/future.hpp
index 175214a..26bf585 100644
--- a/3rdparty/libprocess/include/process/future.hpp
+++ b/3rdparty/libprocess/include/process/future.hpp
@@ -44,6 +44,8 @@
 #include <stout/synchronized.hpp>
 #include <stout/try.hpp>
 
+#include <stout/os/strerror.hpp>
+
 namespace process {
 
 // Forward declarations (instead of include to break circular dependency).
@@ -76,6 +78,7 @@ class WeakFuture;
 
 // Forward declaration of Failure.
 struct Failure;
+struct ErrnoFailure;
 
 
 // Definition of a "shared" future. A future can hold any
@@ -97,6 +100,8 @@ public:
 
   /*implicit*/ Future(const Failure& failure);
 
+  /*implicit*/ Future(const ErrnoFailure& failure);
+
   /*implicit*/ Future(const Future<T>& that);
 
   /*implicit*/ Future(Future<T>&& that);
@@ -536,6 +541,23 @@ struct Failure
 };
 
 
+struct ErrnoFailure : public Failure
+{
+  ErrnoFailure() : ErrnoFailure(errno) {}
+
+  explicit ErrnoFailure(int _code)
+    : Failure(os::strerror(_code)), code(_code) {}
+
+  explicit ErrnoFailure(const std::string& message)
+    : ErrnoFailure(errno, message) {}
+
+  ErrnoFailure(int _code, const std::string& message)
+    : Failure(message + ": " + os::strerror(_code)), code(_code) {}
+
+  const int code;
+};
+
+
 // Forward declaration to use as friend below.
 namespace internal {
 template <typename U>
@@ -928,6 +950,14 @@ Future<T>::Future(const Failure& failure)
 
 
 template <typename T>
+Future<T>::Future(const ErrnoFailure& failure)
+  : data(new Data())
+{
+  fail(failure.message);
+}
+
+
+template <typename T>
 Future<T>::Future(const Future<T>& that)
   : data(that.data) {}
 


[9/9] mesos git commit: Added a DUP2 child hook to Subprocess.

Posted by ji...@apache.org.
Added a DUP2 child hook to Subprocess.

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


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

Branch: refs/heads/master
Commit: d6bc482ac40063a5b37f672b2591a07d3ebc3c4d
Parents: f035082
Author: Jie Yu <yu...@gmail.com>
Authored: Sun Dec 4 13:14:59 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/subprocess_base.hpp |  7 +++++++
 3rdparty/libprocess/src/subprocess.cpp                  | 10 ++++++++++
 2 files changed, 17 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d6bc482a/3rdparty/libprocess/include/process/subprocess_base.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/subprocess_base.hpp b/3rdparty/libprocess/include/process/subprocess_base.hpp
index 1d02454..0d9c74a 100644
--- a/3rdparty/libprocess/include/process/subprocess_base.hpp
+++ b/3rdparty/libprocess/include/process/subprocess_base.hpp
@@ -199,6 +199,13 @@ public:
      */
     static ChildHook SETSID();
 
+#ifndef __WINDOWS__
+    /**
+     * `ChildHook` for duplicating a file descriptor.
+     */
+    static ChildHook DUP2(int oldFd, int newFd);
+#endif // __WINDOWS__
+
     /**
      * `ChildHook` for starting a Supervisor process monitoring
      *  and killing the child process if the parent process terminates.

http://git-wip-us.apache.org/repos/asf/mesos/blob/d6bc482a/3rdparty/libprocess/src/subprocess.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess.cpp b/3rdparty/libprocess/src/subprocess.cpp
index 284e22e..b3efb9c 100644
--- a/3rdparty/libprocess/src/subprocess.cpp
+++ b/3rdparty/libprocess/src/subprocess.cpp
@@ -91,6 +91,16 @@ Subprocess::ChildHook Subprocess::ChildHook::SETSID()
 }
 
 
+#ifndef __WINDOWS__
+Subprocess::ChildHook Subprocess::ChildHook::DUP2(int oldFd, int newFd)
+{
+  return Subprocess::ChildHook([oldFd, newFd]() -> Try<Nothing> {
+    return os::dup2(oldFd, newFd);
+  });
+}
+#endif // __WINDOWS__
+
+
 #ifdef __linux__
 inline void signalHandler(int signal)
 {


[5/9] mesos git commit: Added os::setctty to stout.

Posted by ji...@apache.org.
Added os::setctty to stout.

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


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

Branch: refs/heads/master
Commit: 9248867b8401bd9c034f5759198f113d4621ee88
Parents: 5ee6f4f
Author: Jie Yu <yu...@gmail.com>
Authored: Thu Dec 1 18:15:04 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Sun Dec 4 21:41:51 2016 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/posix/os.hpp | 11 +++++++++++
 1 file changed, 11 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9248867b/3rdparty/stout/include/stout/posix/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/stout/include/stout/posix/os.hpp
index 72e69a00..a8f7108 100644
--- a/3rdparty/stout/include/stout/posix/os.hpp
+++ b/3rdparty/stout/include/stout/posix/os.hpp
@@ -35,6 +35,8 @@
 #include <unistd.h>
 #include <utime.h>
 
+#include <sys/ioctl.h>
+
 #ifdef __linux__
 #include <linux/version.h>
 #include <sys/sysinfo.h>
@@ -489,6 +491,15 @@ inline Try<std::string> ptsname(int master)
   }
 }
 
+
+inline Try<Nothing> setctty(int fd)
+{
+  if (ioctl(fd, TIOCSCTTY, nullptr) == -1) {
+    return ErrnoError();
+  }
+  return Nothing();
+}
+
 } // namespace os {
 
 #endif // __STOUT_POSIX_OS_HPP__