You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by gr...@apache.org on 2017/07/13 00:06:48 UTC

[1/4] mesos git commit: Removed posix/subprocess.hpp dependencies.

Repository: mesos
Updated Branches:
  refs/heads/master e068e84c5 -> c35293ef8


Removed posix/subprocess.hpp dependencies.

Fix a number of places where we were depending on symbols made
visible by <process/posix/subprocess.hpp>. In most cases, this is
just tweaking the includes, but in the Checker we just duplicate
the trivial fork(2) helper since that is easer than trying to
export it as a libprocess API.

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


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

Branch: refs/heads/master
Commit: c48654470bbf13579bd869653724f2b4d3b81ed3
Parents: e068e84
Author: James Peach <jp...@apache.org>
Authored: Wed Jul 12 17:01:11 2017 -0700
Committer: Greg Mann <gr...@gmail.com>
Committed: Wed Jul 12 17:01:11 2017 -0700

----------------------------------------------------------------------
 src/checks/checker_process.cpp                      | 16 ++++++++++++++--
 .../containerizer/mesos/isolators/volume/image.cpp  |  3 +++
 src/uri/fetchers/docker.cpp                         |  1 +
 3 files changed, 18 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c4865447/src/checks/checker_process.cpp
----------------------------------------------------------------------
diff --git a/src/checks/checker_process.cpp b/src/checks/checker_process.cpp
index 66f5452..d92588e 100644
--- a/src/checks/checker_process.cpp
+++ b/src/checks/checker_process.cpp
@@ -105,7 +105,7 @@ static pid_t cloneWithSetns(
     const Option<pid_t>& taskPid,
     const vector<string>& namespaces)
 {
-  return process::defaultClone([=]() -> int {
+  auto child = [=]() -> int {
     if (taskPid.isSome()) {
       foreach (const string& ns, namespaces) {
         Try<Nothing> setns = ns::setns(taskPid.get(), ns);
@@ -121,7 +121,19 @@ static pid_t cloneWithSetns(
     }
 
     return func();
-  });
+  };
+
+  pid_t pid = ::fork();
+  if (pid == -1) {
+    return -1;
+  } else if (pid == 0) {
+    // Child.
+    ::exit(child());
+    UNREACHABLE();
+  } else {
+    // Parent.
+    return pid;
+  }
 }
 #endif
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c4865447/src/slave/containerizer/mesos/isolators/volume/image.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp
index c89af3e..35966aa 100644
--- a/src/slave/containerizer/mesos/isolators/volume/image.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -28,6 +28,9 @@
 #include <stout/foreach.hpp>
 #include <stout/strings.hpp>
 
+#include <stout/os/exists.hpp>
+#include <stout/os/mkdir.hpp>
+
 #include "slave/containerizer/mesos/isolators/volume/image.hpp"
 
 #include "slave/containerizer/mesos/provisioner/provisioner.hpp"

http://git-wip-us.apache.org/repos/asf/mesos/blob/c4865447/src/uri/fetchers/docker.cpp
----------------------------------------------------------------------
diff --git a/src/uri/fetchers/docker.cpp b/src/uri/fetchers/docker.cpp
index 7f3e4e7..91db13b 100644
--- a/src/uri/fetchers/docker.cpp
+++ b/src/uri/fetchers/docker.cpp
@@ -32,6 +32,7 @@
 #include <stout/strings.hpp>
 
 #include <stout/os/constants.hpp>
+#include <stout/os/getenv.hpp>
 #include <stout/os/mkdir.hpp>
 #include <stout/os/write.hpp>
 


[3/4] mesos git commit: Removed subprocess_base.hpp.

Posted by gr...@apache.org.
Removed subprocess_base.hpp.

Since subprocess_base.hpp no longer contains any definitions,
remove the unnecessary indirection by renaming it to
subprocess.hpp

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


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

Branch: refs/heads/master
Commit: 350f72d92a172dbdc321793990c691dde30c83aa
Parents: e38ed10
Author: James Peach <jp...@apache.org>
Authored: Wed Jul 12 17:01:14 2017 -0700
Committer: Greg Mann <gr...@gmail.com>
Committed: Wed Jul 12 17:01:14 2017 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/Makefile.am         |   1 -
 .../libprocess/include/process/subprocess.hpp   | 421 +++++++++++++++++-
 .../include/process/subprocess_base.hpp         | 435 -------------------
 3 files changed, 418 insertions(+), 439 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/350f72d9/3rdparty/libprocess/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/Makefile.am b/3rdparty/libprocess/include/Makefile.am
index e6aebf0..258e2ca 100644
--- a/3rdparty/libprocess/include/Makefile.am
+++ b/3rdparty/libprocess/include/Makefile.am
@@ -64,7 +64,6 @@ nobase_include_HEADERS =		\
   process/statistics.hpp		\
   process/system.hpp			\
   process/subprocess.hpp		\
-  process/subprocess_base.hpp		\
   process/ssl/flags.hpp			\
   process/ssl/gtest.hpp			\
   process/ssl/utilities.hpp		\

http://git-wip-us.apache.org/repos/asf/mesos/blob/350f72d9/3rdparty/libprocess/include/process/subprocess.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/subprocess.hpp b/3rdparty/libprocess/include/process/subprocess.hpp
index e259ac0..6a12623 100644
--- a/3rdparty/libprocess/include/process/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/subprocess.hpp
@@ -13,8 +13,423 @@
 #ifndef __PROCESS_SUBPROCESS_HPP__
 #define __PROCESS_SUBPROCESS_HPP__
 
-// Various declarations appear in this header, and must be included before we
-// include the platform-dependent versions of the headers.
-#include <process/subprocess_base.hpp>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <process/future.hpp>
+
+#include <stout/flags.hpp>
+#include <stout/lambda.hpp>
+#include <stout/none.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+#include <stout/os/shell.hpp>
+#include <stout/os/int_fd.hpp>
+
+
+namespace process {
+
+/**
+ * Represents a fork() exec()ed subprocess. Access is provided to the
+ * input / output of the process, as well as the exit status. The
+ * input / output file descriptors are only closed after:
+ *   1. The subprocess has terminated.
+ *   2. There are no longer any references to the associated
+ *      Subprocess object.
+ */
+class Subprocess
+{
+public:
+  // Forward declarations.
+  struct ParentHook;
+  class ChildHook;
+
+  /**
+   * Describes how the I/O is redirected for stdin/stdout/stderr.
+   * One of the following three modes are supported:
+   *   1. PIPE: Redirect to a pipe.  The pipe will be created when
+   *      launching a subprocess and the user can read/write the
+   *      parent side of the pipe using `Subprocess::in/out/err`.
+   *   2. PATH: Redirect to a file.  For stdout/stderr, the file will
+   *      be created if it does not exist.  If the file exists, it
+   *      will be appended.
+   *   3. FD: Redirect to an open file descriptor.
+   */
+  class IO
+  {
+  public:
+    /**
+     * For input file descriptors a child reads from the `read` file
+     * descriptor and a parent may write to the `write` file
+     * descriptor if one is present.
+     *
+     * NOTE: We initialize `read` to -1 so that we do not close an
+     * arbitrary file descriptor, in case we encounter an error
+     * while starting a subprocess (closing -1 is always a no-op).
+     */
+    struct InputFileDescriptors
+    {
+      int_fd read = -1;
+      Option<int_fd> write = None();
+    };
+
+    /**
+     * For output file descriptors a child writes to the `write` file
+     * descriptor and a parent may read from the `read` file
+     * descriptor if one is present.
+     *
+     * NOTE: We initialize `write` to -1 so that we do not close an
+     * arbitrary file descriptor, in case we encounter an error
+     * while starting a subprocess (closing -1 is always a no-op).
+     */
+    struct OutputFileDescriptors
+    {
+      Option<int_fd> read = None();
+      int_fd write = -1;
+    };
+
+    /**
+     * Describes the lifecycle of a file descriptor passed into a subprocess
+     * via the `Subprocess::FD` helper.
+     */
+    enum FDType {
+      /**
+       * The file descriptor is duplicated before being passed to the
+       * subprocess.  The original file descriptor remains open.
+       */
+      DUPLICATED,
+
+      /**
+       * The file descriptor is not duplicated before being passed to the
+       * subprocess.  Upon spawning the subprocess, the original file
+       * descriptor is closed in the parent and remains open in the child.
+       */
+      OWNED
+    };
+
+
+  private:
+    friend class Subprocess;
+
+    friend Try<Subprocess> subprocess(
+        const std::string& path,
+        std::vector<std::string> argv,
+        const Subprocess::IO& in,
+        const Subprocess::IO& out,
+        const Subprocess::IO& err,
+        const flags::FlagsBase* flags,
+        const Option<std::map<std::string, std::string>>& environment,
+        const Option<lambda::function<
+            pid_t(const lambda::function<int()>&)>>& clone,
+        const std::vector<Subprocess::ParentHook>& parent_hooks,
+        const std::vector<Subprocess::ChildHook>& child_hooks);
+
+    IO(const lambda::function<Try<InputFileDescriptors>()>& _input,
+       const lambda::function<Try<OutputFileDescriptors>()>& _output)
+      : input(_input),
+        output(_output) {}
+
+    /**
+     * Prepares a set of file descriptors for stdin of a subprocess.
+     */
+    lambda::function<Try<InputFileDescriptors>()> input;
+
+    /**
+     * Prepares a set of file descriptors for stdout/stderr of a subprocess.
+     */
+    lambda::function<Try<OutputFileDescriptors>()> output;
+  };
+
+  /**
+   * A hook can be passed to a `subprocess` call. It provides a way to
+   * inject dynamic implementation behavior between the clone and exec
+   * calls in the parent process.
+   */
+  struct ParentHook
+  {
+    ParentHook(const lambda::function<Try<Nothing>(pid_t)>& _parent_setup);
+
+    /**
+     * The callback that must be specified for execution after the
+     * child has been cloned, but before it starts executing the new
+     * process. This provides access to the child pid after its
+     * initialization to add tracking or modify execution state of
+     * the child before it executes the new process.
+     */
+    const lambda::function<Try<Nothing>(pid_t)> parent_setup;
+
+    friend class Subprocess;
+
+#ifdef __WINDOWS__
+    /**
+     * A Windows Job Object is used to manage groups of processes, which
+     * we use due to the lack of a process hierarchy (in a UNIX sense)
+     * on Windows.
+     *
+     * This hook places the subprocess into a Job Object, which will allow
+     * us to kill the subprocess and all of its children together.
+     */
+    static ParentHook CREATE_JOB();
+#endif // __WINDOWS__
+  };
+
+  /**
+   * A `ChildHook` can be passed to a `subprocess` call. It provides a way to
+   * inject predefined behavior between the clone and exec calls in the
+   * child process.
+   * As such `ChildHooks` have to fulfill certain criteria (especially
+   * being async safe) the class does not offer a public constructor.
+   * Instead instances can be created via factory methods.
+   * NOTE: Returning an error from a childHook causes the child process to
+   * abort.
+   */
+  class ChildHook
+  {
+  public:
+    /**
+     * `ChildHook` for changing the working directory.
+     */
+    static ChildHook CHDIR(const std::string& working_directory);
+
+    /**
+     * `ChildHook` for generating a new session id.
+     */
+    static ChildHook SETSID();
+
+#ifndef __WINDOWS__
+    /**
+     * `ChildHook` for duplicating a file descriptor.
+     */
+    static ChildHook DUP2(int oldFd, int newFd);
+
+    /**
+     * `ChildHook` to unset CLOEXEC on a file descriptor. This is
+     * useful to explicitly pass an FD to a subprocess.
+     */
+    static ChildHook UNSET_CLOEXEC(int fd);
+#endif // __WINDOWS__
+
+    /**
+     * `ChildHook` for starting a Supervisor process monitoring
+     *  and killing the child process if the parent process terminates.
+     *
+     * NOTE: The supervisor process sets the process group id in order for it
+     * and its child processes to be killed together. We should not (re)set the
+     * sid after this.
+     */
+    static ChildHook SUPERVISOR();
+
+    Try<Nothing> operator()() const { return child_setup(); }
+
+  private:
+    ChildHook(const lambda::function<Try<Nothing>()>& _child_setup);
+
+    const lambda::function<Try<Nothing>()> child_setup;
+  };
+
+  // Some syntactic sugar to create an IO::PIPE redirector.
+  static IO PIPE();
+  static IO PATH(const std::string& path);
+  static IO FD(int_fd fd, IO::FDType type = IO::DUPLICATED);
+
+  /**
+   * @return The operating system PID for this subprocess.
+   */
+  pid_t pid() const { return data->pid; }
+
+  /**
+   * @return File descriptor representing the parent side (i.e.,
+   *     write side) of this subprocess' stdin pipe or None if no pipe
+   *     was requested.
+   */
+  Option<int_fd> in() const
+  {
+    return data->in;
+  }
+
+  /**
+   * @return File descriptor representing the parent side (i.e., write
+   *     side) of this subprocess' stdout pipe or None if no pipe was
+   *     requested.
+   */
+  Option<int_fd> out() const
+  {
+    return data->out;
+  }
+
+  /**
+   * @return File descriptor representing the parent side (i.e., write
+   *     side) of this subprocess' stderr pipe or None if no pipe was
+   *     requested.
+   */
+  Option<int_fd> err() const
+  {
+    return data->err;
+  }
+
+  /**
+   * Exit status of this subprocess captured as a Future (completed
+   * when the subprocess exits).
+   *
+   * On Posix, the exit status is propagated from an underlying call
+   * to `waitpid` and can be used with macros defined in wait.h, i.e.,
+   * `WIFEXITED(status)`.
+   *
+   * On Windows, the exit status contains the exit code from an
+   * underlying call to `GetExitCodeProcess()`.
+   *
+   * TODO(alexr): Ensure the code working with `status` is portable by
+   * either making `WIFEXITED` family macros no-op on Windows or
+   * converting `status` to a tuple <termination status, exit code>,
+   * see MESOS-7242.
+   *
+   * NOTE: Discarding this future has no effect on the subprocess!
+   *
+   * @return Future from doing a `process::reap()` of this subprocess.
+   *     Note that `process::reap()` never fails or discards this future.
+   */
+  Future<Option<int>> status() const { return data->status; }
+
+private:
+  friend Try<Subprocess> subprocess(
+      const std::string& path,
+      std::vector<std::string> argv,
+      const Subprocess::IO& in,
+      const Subprocess::IO& out,
+      const Subprocess::IO& err,
+      const flags::FlagsBase* flags,
+      const Option<std::map<std::string, std::string>>& environment,
+      const Option<lambda::function<
+          pid_t(const lambda::function<int()>&)>>& clone,
+      const std::vector<Subprocess::ParentHook>& parent_hooks,
+      const std::vector<Subprocess::ChildHook>& child_hooks);
+
+  struct Data
+  {
+    ~Data()
+    {
+      if (in.isSome()) { os::close(in.get()); }
+      if (out.isSome()) { os::close(out.get()); }
+      if (err.isSome()) { os::close(err.get()); }
+    }
+
+    pid_t pid;
+
+#ifdef __WINDOWS__
+    Option<::internal::windows::ProcessData> process_data;
+#endif // __WINDOWS__
+
+    // The parent side of the pipe for stdin/stdout/stderr. If the
+    // IO mode is not a pipe, `None` will be stored.
+    // NOTE: stdin, stdout, stderr are macros on some systems, hence
+    // these names instead.
+    Option<int_fd> in;
+    Option<int_fd> out;
+    Option<int_fd> err;
+
+    Future<Option<int>> status;
+  };
+
+  Subprocess() : data(new Data()) {}
+
+  std::shared_ptr<Data> data;
+};
+
+using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
+using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;
+
+/**
+ * Forks a subprocess and execs the specified 'path' with the
+ * specified 'argv', redirecting stdin, stdout, and stderr as
+ * specified by 'in', 'out', and 'err' respectively.
+ *
+ * @param path Relative or absolute path in the filesytem to the
+ *     executable.
+ * @param argv Argument vector to pass to exec.
+ * @param in Redirection specification for stdin.
+ * @param out Redirection specification for stdout.
+ * @param err Redirection specification for stderr.
+ * @param flags Flags to be stringified and appended to 'argv'.
+ * @param environment Environment variables to use for the new
+ *     subprocess or if None (the default) then the new subprocess
+ *     will inherit the environment of the current process.
+ * @param clone Function to be invoked in order to fork/clone the
+ *     subprocess.
+ * @param parent_hooks Hooks that will be executed in the parent
+ *     before the child execs.
+ * @param child_hooks Hooks that will be executed in the child
+ *     before the child execs but after parent_hooks have executed.
+ * @return The subprocess or an error if one occurred.
+ */
+// TODO(jmlvanre): Consider removing default argument for
+// `parent_hooks` to force the caller to think about setting them.
+Try<Subprocess> subprocess(
+    const std::string& path,
+    std::vector<std::string> argv,
+    const Subprocess::IO& in = Subprocess::FD(STDIN_FILENO),
+    const Subprocess::IO& out = Subprocess::FD(STDOUT_FILENO),
+    const Subprocess::IO& err = Subprocess::FD(STDERR_FILENO),
+    const flags::FlagsBase* flags = nullptr,
+    const Option<std::map<std::string, std::string>>& environment = None(),
+    const Option<lambda::function<
+        pid_t(const lambda::function<int()>&)>>& clone = None(),
+    const std::vector<Subprocess::ParentHook>& parent_hooks = {},
+    const std::vector<Subprocess::ChildHook>& child_hooks = {});
+
+
+/**
+ * Overload of 'subprocess' for launching a shell command, i.e., 'sh
+ * -c command'.
+ *
+ * Currently, we do not support flags for shell command variants due
+ * to the complexity involved in escaping quotes in flags.
+ *
+ * @param command Shell command to execute.
+ * @param in Redirection specification for stdin.
+ * @param out Redirection specification for stdout.
+ * @param err Redirection specification for stderr.
+ * @param environment Environment variables to use for the new
+ *     subprocess or if None (the default) then the new subprocess
+ *     will inherit the environment of the current process.
+ * @param clone Function to be invoked in order to fork/clone the
+ *     subprocess.
+ * @param parent_hooks Hooks that will be executed in the parent
+ *     before the child execs.
+ * @param child_hooks Hooks that will be executed in the child
+ *     before the child execs but after parent_hooks have executed.
+ * @return The subprocess or an error if one occurred.
+ */
+// TODO(jmlvanre): Consider removing default argument for
+// `parent_hooks` to force the caller to think about setting them.
+inline Try<Subprocess> subprocess(
+    const std::string& command,
+    const Subprocess::IO& in = Subprocess::FD(STDIN_FILENO),
+    const Subprocess::IO& out = Subprocess::FD(STDOUT_FILENO),
+    const Subprocess::IO& err = Subprocess::FD(STDERR_FILENO),
+    const Option<std::map<std::string, std::string>>& environment = None(),
+    const Option<lambda::function<
+        pid_t(const lambda::function<int()>&)>>& clone = None(),
+    const std::vector<Subprocess::ParentHook>& parent_hooks = {},
+    const std::vector<Subprocess::ChildHook>& child_hooks = {})
+{
+  std::vector<std::string> argv = {os::Shell::arg0, os::Shell::arg1, command};
+
+  return subprocess(
+      os::Shell::name,
+      argv,
+      in,
+      out,
+      err,
+      nullptr,
+      environment,
+      clone,
+      parent_hooks,
+      child_hooks);
+}
+
+} // namespace process {
 
 #endif // __PROCESS_SUBPROCESS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/350f72d9/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
deleted file mode 100644
index 898ce94..0000000
--- a/3rdparty/libprocess/include/process/subprocess_base.hpp
+++ /dev/null
@@ -1,435 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-
-#ifndef __PROCESS_SUBPROCESS_BASE_HPP__
-#define __PROCESS_SUBPROCESS_BASE_HPP__
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <process/future.hpp>
-
-#include <stout/flags.hpp>
-#include <stout/lambda.hpp>
-#include <stout/none.hpp>
-#include <stout/option.hpp>
-#include <stout/try.hpp>
-
-#include <stout/os/shell.hpp>
-#include <stout/os/int_fd.hpp>
-
-
-namespace process {
-
-/**
- * Represents a fork() exec()ed subprocess. Access is provided to the
- * input / output of the process, as well as the exit status. The
- * input / output file descriptors are only closed after:
- *   1. The subprocess has terminated.
- *   2. There are no longer any references to the associated
- *      Subprocess object.
- */
-class Subprocess
-{
-public:
-  // Forward declarations.
-  struct ParentHook;
-  class ChildHook;
-
-  /**
-   * Describes how the I/O is redirected for stdin/stdout/stderr.
-   * One of the following three modes are supported:
-   *   1. PIPE: Redirect to a pipe.  The pipe will be created when
-   *      launching a subprocess and the user can read/write the
-   *      parent side of the pipe using `Subprocess::in/out/err`.
-   *   2. PATH: Redirect to a file.  For stdout/stderr, the file will
-   *      be created if it does not exist.  If the file exists, it
-   *      will be appended.
-   *   3. FD: Redirect to an open file descriptor.
-   */
-  class IO
-  {
-  public:
-    /**
-     * For input file descriptors a child reads from the `read` file
-     * descriptor and a parent may write to the `write` file
-     * descriptor if one is present.
-     *
-     * NOTE: We initialize `read` to -1 so that we do not close an
-     * arbitrary file descriptor, in case we encounter an error
-     * while starting a subprocess (closing -1 is always a no-op).
-     */
-    struct InputFileDescriptors
-    {
-      int_fd read = -1;
-      Option<int_fd> write = None();
-    };
-
-    /**
-     * For output file descriptors a child writes to the `write` file
-     * descriptor and a parent may read from the `read` file
-     * descriptor if one is present.
-     *
-     * NOTE: We initialize `write` to -1 so that we do not close an
-     * arbitrary file descriptor, in case we encounter an error
-     * while starting a subprocess (closing -1 is always a no-op).
-     */
-    struct OutputFileDescriptors
-    {
-      Option<int_fd> read = None();
-      int_fd write = -1;
-    };
-
-    /**
-     * Describes the lifecycle of a file descriptor passed into a subprocess
-     * via the `Subprocess::FD` helper.
-     */
-    enum FDType {
-      /**
-       * The file descriptor is duplicated before being passed to the
-       * subprocess.  The original file descriptor remains open.
-       */
-      DUPLICATED,
-
-      /**
-       * The file descriptor is not duplicated before being passed to the
-       * subprocess.  Upon spawning the subprocess, the original file
-       * descriptor is closed in the parent and remains open in the child.
-       */
-      OWNED
-    };
-
-
-  private:
-    friend class Subprocess;
-
-    friend Try<Subprocess> subprocess(
-        const std::string& path,
-        std::vector<std::string> argv,
-        const Subprocess::IO& in,
-        const Subprocess::IO& out,
-        const Subprocess::IO& err,
-        const flags::FlagsBase* flags,
-        const Option<std::map<std::string, std::string>>& environment,
-        const Option<lambda::function<
-            pid_t(const lambda::function<int()>&)>>& clone,
-        const std::vector<Subprocess::ParentHook>& parent_hooks,
-        const std::vector<Subprocess::ChildHook>& child_hooks);
-
-    IO(const lambda::function<Try<InputFileDescriptors>()>& _input,
-       const lambda::function<Try<OutputFileDescriptors>()>& _output)
-      : input(_input),
-        output(_output) {}
-
-    /**
-     * Prepares a set of file descriptors for stdin of a subprocess.
-     */
-    lambda::function<Try<InputFileDescriptors>()> input;
-
-    /**
-     * Prepares a set of file descriptors for stdout/stderr of a subprocess.
-     */
-    lambda::function<Try<OutputFileDescriptors>()> output;
-  };
-
-  /**
-   * A hook can be passed to a `subprocess` call. It provides a way to
-   * inject dynamic implementation behavior between the clone and exec
-   * calls in the parent process.
-   */
-  struct ParentHook
-  {
-    ParentHook(const lambda::function<Try<Nothing>(pid_t)>& _parent_setup);
-
-    /**
-     * The callback that must be specified for execution after the
-     * child has been cloned, but before it starts executing the new
-     * process. This provides access to the child pid after its
-     * initialization to add tracking or modify execution state of
-     * the child before it executes the new process.
-     */
-    const lambda::function<Try<Nothing>(pid_t)> parent_setup;
-
-    friend class Subprocess;
-
-#ifdef __WINDOWS__
-    /**
-     * A Windows Job Object is used to manage groups of processes, which
-     * we use due to the lack of a process hierarchy (in a UNIX sense)
-     * on Windows.
-     *
-     * This hook places the subprocess into a Job Object, which will allow
-     * us to kill the subprocess and all of its children together.
-     */
-    static ParentHook CREATE_JOB();
-#endif // __WINDOWS__
-  };
-
-  /**
-   * A `ChildHook` can be passed to a `subprocess` call. It provides a way to
-   * inject predefined behavior between the clone and exec calls in the
-   * child process.
-   * As such `ChildHooks` have to fulfill certain criteria (especially
-   * being async safe) the class does not offer a public constructor.
-   * Instead instances can be created via factory methods.
-   * NOTE: Returning an error from a childHook causes the child process to
-   * abort.
-   */
-  class ChildHook
-  {
-  public:
-    /**
-     * `ChildHook` for changing the working directory.
-     */
-    static ChildHook CHDIR(const std::string& working_directory);
-
-    /**
-     * `ChildHook` for generating a new session id.
-     */
-    static ChildHook SETSID();
-
-#ifndef __WINDOWS__
-    /**
-     * `ChildHook` for duplicating a file descriptor.
-     */
-    static ChildHook DUP2(int oldFd, int newFd);
-
-    /**
-     * `ChildHook` to unset CLOEXEC on a file descriptor. This is
-     * useful to explicitly pass an FD to a subprocess.
-     */
-    static ChildHook UNSET_CLOEXEC(int fd);
-#endif // __WINDOWS__
-
-    /**
-     * `ChildHook` for starting a Supervisor process monitoring
-     *  and killing the child process if the parent process terminates.
-     *
-     * NOTE: The supervisor process sets the process group id in order for it
-     * and its child processes to be killed together. We should not (re)set the
-     * sid after this.
-     */
-    static ChildHook SUPERVISOR();
-
-    Try<Nothing> operator()() const { return child_setup(); }
-
-  private:
-    ChildHook(const lambda::function<Try<Nothing>()>& _child_setup);
-
-    const lambda::function<Try<Nothing>()> child_setup;
-  };
-
-  // Some syntactic sugar to create an IO::PIPE redirector.
-  static IO PIPE();
-  static IO PATH(const std::string& path);
-  static IO FD(int_fd fd, IO::FDType type = IO::DUPLICATED);
-
-  /**
-   * @return The operating system PID for this subprocess.
-   */
-  pid_t pid() const { return data->pid; }
-
-  /**
-   * @return File descriptor representing the parent side (i.e.,
-   *     write side) of this subprocess' stdin pipe or None if no pipe
-   *     was requested.
-   */
-  Option<int_fd> in() const
-  {
-    return data->in;
-  }
-
-  /**
-   * @return File descriptor representing the parent side (i.e., write
-   *     side) of this subprocess' stdout pipe or None if no pipe was
-   *     requested.
-   */
-  Option<int_fd> out() const
-  {
-    return data->out;
-  }
-
-  /**
-   * @return File descriptor representing the parent side (i.e., write
-   *     side) of this subprocess' stderr pipe or None if no pipe was
-   *     requested.
-   */
-  Option<int_fd> err() const
-  {
-    return data->err;
-  }
-
-  /**
-   * Exit status of this subprocess captured as a Future (completed
-   * when the subprocess exits).
-   *
-   * On Posix, the exit status is propagated from an underlying call
-   * to `waitpid` and can be used with macros defined in wait.h, i.e.,
-   * `WIFEXITED(status)`.
-   *
-   * On Windows, the exit status contains the exit code from an
-   * underlying call to `GetExitCodeProcess()`.
-   *
-   * TODO(alexr): Ensure the code working with `status` is portable by
-   * either making `WIFEXITED` family macros no-op on Windows or
-   * converting `status` to a tuple <termination status, exit code>,
-   * see MESOS-7242.
-   *
-   * NOTE: Discarding this future has no effect on the subprocess!
-   *
-   * @return Future from doing a `process::reap()` of this subprocess.
-   *     Note that `process::reap()` never fails or discards this future.
-   */
-  Future<Option<int>> status() const { return data->status; }
-
-private:
-  friend Try<Subprocess> subprocess(
-      const std::string& path,
-      std::vector<std::string> argv,
-      const Subprocess::IO& in,
-      const Subprocess::IO& out,
-      const Subprocess::IO& err,
-      const flags::FlagsBase* flags,
-      const Option<std::map<std::string, std::string>>& environment,
-      const Option<lambda::function<
-          pid_t(const lambda::function<int()>&)>>& clone,
-      const std::vector<Subprocess::ParentHook>& parent_hooks,
-      const std::vector<Subprocess::ChildHook>& child_hooks);
-
-  struct Data
-  {
-    ~Data()
-    {
-      if (in.isSome()) { os::close(in.get()); }
-      if (out.isSome()) { os::close(out.get()); }
-      if (err.isSome()) { os::close(err.get()); }
-    }
-
-    pid_t pid;
-
-#ifdef __WINDOWS__
-    Option<::internal::windows::ProcessData> process_data;
-#endif // __WINDOWS__
-
-    // The parent side of the pipe for stdin/stdout/stderr. If the
-    // IO mode is not a pipe, `None` will be stored.
-    // NOTE: stdin, stdout, stderr are macros on some systems, hence
-    // these names instead.
-    Option<int_fd> in;
-    Option<int_fd> out;
-    Option<int_fd> err;
-
-    Future<Option<int>> status;
-  };
-
-  Subprocess() : data(new Data()) {}
-
-  std::shared_ptr<Data> data;
-};
-
-using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
-using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;
-
-/**
- * Forks a subprocess and execs the specified 'path' with the
- * specified 'argv', redirecting stdin, stdout, and stderr as
- * specified by 'in', 'out', and 'err' respectively.
- *
- * @param path Relative or absolute path in the filesytem to the
- *     executable.
- * @param argv Argument vector to pass to exec.
- * @param in Redirection specification for stdin.
- * @param out Redirection specification for stdout.
- * @param err Redirection specification for stderr.
- * @param flags Flags to be stringified and appended to 'argv'.
- * @param environment Environment variables to use for the new
- *     subprocess or if None (the default) then the new subprocess
- *     will inherit the environment of the current process.
- * @param clone Function to be invoked in order to fork/clone the
- *     subprocess.
- * @param parent_hooks Hooks that will be executed in the parent
- *     before the child execs.
- * @param child_hooks Hooks that will be executed in the child
- *     before the child execs but after parent_hooks have executed.
- * @return The subprocess or an error if one occurred.
- */
-// TODO(jmlvanre): Consider removing default argument for
-// `parent_hooks` to force the caller to think about setting them.
-Try<Subprocess> subprocess(
-    const std::string& path,
-    std::vector<std::string> argv,
-    const Subprocess::IO& in = Subprocess::FD(STDIN_FILENO),
-    const Subprocess::IO& out = Subprocess::FD(STDOUT_FILENO),
-    const Subprocess::IO& err = Subprocess::FD(STDERR_FILENO),
-    const flags::FlagsBase* flags = nullptr,
-    const Option<std::map<std::string, std::string>>& environment = None(),
-    const Option<lambda::function<
-        pid_t(const lambda::function<int()>&)>>& clone = None(),
-    const std::vector<Subprocess::ParentHook>& parent_hooks = {},
-    const std::vector<Subprocess::ChildHook>& child_hooks = {});
-
-
-/**
- * Overload of 'subprocess' for launching a shell command, i.e., 'sh
- * -c command'.
- *
- * Currently, we do not support flags for shell command variants due
- * to the complexity involved in escaping quotes in flags.
- *
- * @param command Shell command to execute.
- * @param in Redirection specification for stdin.
- * @param out Redirection specification for stdout.
- * @param err Redirection specification for stderr.
- * @param environment Environment variables to use for the new
- *     subprocess or if None (the default) then the new subprocess
- *     will inherit the environment of the current process.
- * @param clone Function to be invoked in order to fork/clone the
- *     subprocess.
- * @param parent_hooks Hooks that will be executed in the parent
- *     before the child execs.
- * @param child_hooks Hooks that will be executed in the child
- *     before the child execs but after parent_hooks have executed.
- * @return The subprocess or an error if one occurred.
- */
-// TODO(jmlvanre): Consider removing default argument for
-// `parent_hooks` to force the caller to think about setting them.
-inline Try<Subprocess> subprocess(
-    const std::string& command,
-    const Subprocess::IO& in = Subprocess::FD(STDIN_FILENO),
-    const Subprocess::IO& out = Subprocess::FD(STDOUT_FILENO),
-    const Subprocess::IO& err = Subprocess::FD(STDERR_FILENO),
-    const Option<std::map<std::string, std::string>>& environment = None(),
-    const Option<lambda::function<
-        pid_t(const lambda::function<int()>&)>>& clone = None(),
-    const std::vector<Subprocess::ParentHook>& parent_hooks = {},
-    const std::vector<Subprocess::ChildHook>& child_hooks = {})
-{
-  std::vector<std::string> argv = {os::Shell::arg0, os::Shell::arg1, command};
-
-  return subprocess(
-      os::Shell::name,
-      argv,
-      in,
-      out,
-      err,
-      nullptr,
-      environment,
-      clone,
-      parent_hooks,
-      child_hooks);
-}
-
-} // namespace process {
-
-#endif // __PROCESS_SUBPROCESS_BASE_HPP__


[4/4] mesos git commit: Moved internal libprocess headers to the src directory.

Posted by gr...@apache.org.
Moved internal libprocess headers to the src directory.

The POSIX- and Windows-specific subprocess headers are internal
to libprocess, so move them to the src directory to make it clear
that they don't need to be installed.

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


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

Branch: refs/heads/master
Commit: c35293ef8e70d3b98576aa180935b523003232ce
Parents: 350f72d
Author: James Peach <jp...@apache.org>
Authored: Wed Jul 12 17:01:15 2017 -0700
Committer: Greg Mann <gr...@gmail.com>
Committed: Wed Jul 12 17:01:15 2017 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/Makefile.am                 |   1 +
 3rdparty/libprocess/include/Makefile.am         |   4 -
 .../include/process/posix/subprocess.hpp        | 353 -------------------
 .../include/process/windows/subprocess.hpp      | 102 ------
 3rdparty/libprocess/src/subprocess.cpp          |  12 +-
 3rdparty/libprocess/src/subprocess_posix.hpp    | 353 +++++++++++++++++++
 3rdparty/libprocess/src/subprocess_windows.hpp  | 102 ++++++
 7 files changed, 462 insertions(+), 465 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/3rdparty/libprocess/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/Makefile.am b/3rdparty/libprocess/Makefile.am
index c2190b4..d2b2ed2 100644
--- a/3rdparty/libprocess/Makefile.am
+++ b/3rdparty/libprocess/Makefile.am
@@ -177,6 +177,7 @@ libprocess_la_SOURCES =		\
   src/socket.cpp		\
   src/subprocess.cpp		\
   src/subprocess_posix.cpp	\
+  src/subprocess_posix.hpp	\
   src/time.cpp			\
   src/timeseries.cpp
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/3rdparty/libprocess/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/Makefile.am b/3rdparty/libprocess/include/Makefile.am
index 258e2ca..b452053 100644
--- a/3rdparty/libprocess/include/Makefile.am
+++ b/3rdparty/libprocess/include/Makefile.am
@@ -71,7 +71,3 @@ nobase_include_HEADERS =		\
   process/timeout.hpp			\
   process/timer.hpp			\
   process/timeseries.hpp
-
-noinst_HEADERS = 			\
-  process/posix/subprocess.hpp		\
-  process/windows/subprocess.hpp

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/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
deleted file mode 100644
index b478bec..0000000
--- a/3rdparty/libprocess/include/process/posix/subprocess.hpp
+++ /dev/null
@@ -1,353 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-
-#ifndef __PROCESS_POSIX_SUBPROCESS_HPP__
-#define __PROCESS_POSIX_SUBPROCESS_HPP__
-
-#ifdef __linux__
-#include <sys/prctl.h>
-#endif // __linux__
-#include <sys/types.h>
-
-#include <string>
-
-#include <glog/logging.h>
-
-#include <process/subprocess.hpp>
-
-#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>
-#include <stout/option.hpp>
-#include <stout/os.hpp>
-#include <stout/try.hpp>
-#include <stout/unreachable.hpp>
-
-#include <stout/os/close.hpp>
-#include <stout/os/environment.hpp>
-#include <stout/os/fcntl.hpp>
-#include <stout/os/signals.hpp>
-#include <stout/os/strerror.hpp>
-
-namespace process {
-namespace internal {
-
-static void close(std::initializer_list<int_fd> fds);
-
-
-static void close(
-    const Subprocess::IO::InputFileDescriptors& stdinfds,
-    const Subprocess::IO::OutputFileDescriptors& stdoutfds,
-    const Subprocess::IO::OutputFileDescriptors& stderrfds);
-
-
-inline pid_t defaultClone(const lambda::function<int()>& func)
-{
-  pid_t pid = ::fork();
-  if (pid == -1) {
-    return -1;
-  } else if (pid == 0) {
-    // Child.
-    ::exit(func());
-    UNREACHABLE();
-  } else {
-    // Parent.
-    return pid;
-  }
-}
-
-
-// This function will invoke `os::cloexec` on all specified file
-// descriptors that are valid (i.e., not `None` and >= 0).
-inline Try<Nothing> cloexec(
-    const InputFileDescriptors& stdinfds,
-    const OutputFileDescriptors& stdoutfds,
-    const OutputFileDescriptors& stderrfds)
-{
-  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) {
-    if (fd >= 0) {
-      Try<Nothing> cloexec = os::cloexec(fd);
-      if (cloexec.isError()) {
-        return Error(cloexec.error());
-      }
-    }
-  }
-
-  return Nothing();
-}
-
-
-// The main entry of the child process.
-//
-// NOTE: This function has to be async signal safe.
-inline int childMain(
-    const std::string& path,
-    char** argv,
-    char** envp,
-    const InputFileDescriptors& stdinfds,
-    const OutputFileDescriptors& stdoutfds,
-    const OutputFileDescriptors& stderrfds,
-    bool blocking,
-    int pipes[2],
-    const std::vector<Subprocess::ChildHook>& child_hooks)
-{
-  // Close parent's end of the pipes.
-  if (stdinfds.write.isSome()) {
-    ::close(stdinfds.write.get());
-  }
-  if (stdoutfds.read.isSome()) {
-    ::close(stdoutfds.read.get());
-  }
-  if (stderrfds.read.isSome()) {
-    ::close(stderrfds.read.get());
-  }
-
-  // Currently we will block the child's execution of the new process
-  // until all the parent hooks (if any) have executed.
-  if (blocking) {
-    ::close(pipes[1]);
-  }
-
-  // Redirect I/O for stdin/stdout/stderr.
-  while (::dup2(stdinfds.read, STDIN_FILENO) == -1 && errno == EINTR);
-  while (::dup2(stdoutfds.write, STDOUT_FILENO) == -1 && errno == EINTR);
-  while (::dup2(stderrfds.write, STDERR_FILENO) == -1 && errno == EINTR);
-
-  // Close the copies. We need to make sure that we do not close the
-  // file descriptor assigned to stdin/stdout/stderr in case the
-  // 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) {
-    ::close(stdinfds.read);
-  }
-  if (stdoutfds.write != STDIN_FILENO &&
-      stdoutfds.write != STDOUT_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 != stdinfds.read &&
-      stderrfds.write != stdoutfds.write) {
-    ::close(stderrfds.write);
-  }
-
-  if (blocking) {
-    // 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");
-    }
-
-    // Now close the pipe as we don't need it anymore.
-    ::close(pipes[0]);
-  }
-
-  // Run the child hooks.
-  foreach (const Subprocess::ChildHook& hook, child_hooks) {
-    Try<Nothing> callback = hook();
-
-    // If the callback failed, we should abort execution.
-    if (callback.isError()) {
-      ABORT("Failed to execute Subprocess::ChildHook: " + callback.error());
-    }
-  }
-
-  os::execvpe(path.c_str(), argv, envp);
-
-  ABORT("Failed to os::execvpe on path '" + path + "': " + os::strerror(errno));
-}
-
-
-inline Try<pid_t> cloneChild(
-    const std::string& path,
-    std::vector<std::string> argv,
-    const Option<std::map<std::string, std::string>>& environment,
-    const Option<lambda::function<
-        pid_t(const lambda::function<int()>&)>>& _clone,
-    const std::vector<Subprocess::ParentHook>& parent_hooks,
-    const std::vector<Subprocess::ChildHook>& child_hooks,
-    const InputFileDescriptors stdinfds,
-    const OutputFileDescriptors stdoutfds,
-    const OutputFileDescriptors stderrfds)
-{
-  // The real arguments that will be passed to 'os::execvpe'. We need
-  // to construct them here before doing the clone as it might not be
-  // async signal safe to perform the memory allocation.
-  char** _argv = new char*[argv.size() + 1];
-  for (size_t i = 0; i < argv.size(); i++) {
-    _argv[i] = (char*) argv[i].c_str();
-  }
-  _argv[argv.size()] = nullptr;
-
-  // Like above, we need to construct the environment that we'll pass
-  // to 'os::execvpe' as it might not be async-safe to perform the
-  // memory allocations.
-  char** envp = os::raw::environment();
-
-  if (environment.isSome()) {
-    // NOTE: We add 1 to the size for a `nullptr` terminator.
-    envp = new char*[environment.get().size() + 1];
-
-    size_t index = 0;
-    foreachpair (
-        const std::string& key,
-        const std::string& value, environment.get()) {
-      std::string entry = key + "=" + value;
-      envp[index] = new char[entry.size() + 1];
-      strncpy(envp[index], entry.c_str(), entry.size() + 1);
-      ++index;
-    }
-
-    envp[index] = nullptr;
-  }
-
-  // Determine the function to clone the child process. If the user
-  // does not specify the clone function, we will use the default.
-  lambda::function<pid_t(const lambda::function<int()>&)> clone =
-    (_clone.isSome() ? _clone.get() : defaultClone);
-
-  // Currently we will block the child's execution of the new process
-  // until all the `parent_hooks` (if any) have executed.
-  std::array<int, 2> pipes;
-  const bool blocking = !parent_hooks.empty();
-
-  if (blocking) {
-    // We assume this should not fail under reasonable conditions so we
-    // use CHECK.
-    Try<std::array<int, 2>> pipe = os::pipe();
-    CHECK_SOME(pipe);
-
-    pipes = pipe.get();
-  }
-
-  // Now, clone the child process.
-  pid_t pid = clone(lambda::bind(
-      &childMain,
-      path,
-      _argv,
-      envp,
-      stdinfds,
-      stdoutfds,
-      stderrfds,
-      blocking,
-      pipes.data(),
-      child_hooks));
-
-  delete[] _argv;
-
-  // Need to delete 'envp' if we had environment variables passed to
-  // us and we needed to allocate the space.
-  if (environment.isSome()) {
-    CHECK_NE(os::raw::environment(), envp);
-
-    // We ignore the last 'envp' entry since it is nullptr.
-    for (size_t index = 0; index < environment->size(); index++) {
-      delete[] envp[index];
-    }
-
-    delete[] envp;
-  }
-
-  if (pid == -1) {
-    // Save the errno as 'close' below might overwrite it.
-    ErrnoError error("Failed to clone");
-    internal::close(stdinfds, stdoutfds, stderrfds);
-
-    if (blocking) {
-      os::close(pipes[0]);
-      os::close(pipes[1]);
-    }
-
-    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]);
-
-    // Run the parent hooks.
-    foreach (const Subprocess::ParentHook& hook, parent_hooks) {
-      Try<Nothing> parentSetup = hook.parent_setup(pid);
-
-      // If the hook callback fails, we shouldn't proceed with the
-      // execution and hence the child process should be killed.
-      if (parentSetup.isError()) {
-        LOG(WARNING)
-          << "Failed to execute Subprocess::ParentHook in parent for child '"
-          << pid << "': " << parentSetup.error();
-
-        os::close(pipes[1]);
-
-        // Ensure the child is killed.
-        ::kill(pid, SIGKILL);
-
-        return Error(
-            "Failed to execute Subprocess::ParentHook in parent for child '" +
-            stringify(pid) + "': " + parentSetup.error());
-      }
-    }
-
-    // Now that we've executed the parent hooks, we can signal the child 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(pid, SIGKILL);
-
-      return Error("Failed to synchronize child process");
-    }
-  }
-
-  return pid;
-}
-
-}  // namespace internal {
-}  // namespace process {
-
-#endif // __PROCESS_POSIX_SUBPROCESS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/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
deleted file mode 100644
index 0183bb4..0000000
--- a/3rdparty/libprocess/include/process/windows/subprocess.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-
-#ifndef __PROCESS_WINDOWS_SUBPROCESS_HPP__
-#define __PROCESS_WINDOWS_SUBPROCESS_HPP__
-
-#include <signal.h>
-
-#include <string>
-#include <tuple>
-
-#include <glog/logging.h>
-
-#include <process/subprocess.hpp>
-
-#include <stout/error.hpp>
-#include <stout/foreach.hpp>
-#include <stout/hashset.hpp>
-#include <stout/option.hpp>
-#include <stout/os.hpp>
-#include <stout/os/shell.hpp>
-#include <stout/try.hpp>
-#include <stout/windows.hpp>
-
-#include <stout/os/close.hpp>
-#include <stout/os/environment.hpp>
-
-#include <userEnv.h>
-
-namespace process {
-namespace internal {
-
-// NOTE: We are expecting that components of `argv` that need to be quoted
-// (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
-// to have been already quoted correctly before we generate `command`.
-// Incorrectly-quoted command arguments will probably lead the child process
-// to terminate with an error. See also NOTE on `process::subprocess`.
-inline Try<::internal::windows::ProcessData> createChildProcess(
-    const std::string& path,
-    const std::vector<std::string>& argv,
-    const Option<std::map<std::string, std::string>>& environment,
-    const std::vector<Subprocess::ParentHook>& parent_hooks,
-    const InputFileDescriptors stdinfds,
-    const OutputFileDescriptors stdoutfds,
-    const OutputFileDescriptors stderrfds)
-{
-  Try<::internal::windows::ProcessData> process_data =
-    ::internal::windows::create_process(
-        path,
-        argv,
-        environment,
-        true, // Create suspended.
-        std::make_tuple(stdinfds.read, stdoutfds.write, stderrfds.write));
-
-  if (process_data.isError()) {
-    return process_data;
-  }
-
-  // Run the parent hooks.
-  const pid_t pid = process_data.get().pid;
-  foreach (const Subprocess::ParentHook& hook, parent_hooks) {
-    Try<Nothing> parentSetup = hook.parent_setup(pid);
-
-    // If the hook callback fails, we shouldn't proceed with the
-    // execution and hence the child process should be killed.
-    if (parentSetup.isError()) {
-      // Attempt to kill the process. Since it is still in suspended state, we
-      // do not need to kill any descendents. We also can't use `os::kill_job`
-      // because this process is not in a Job Object unless one of the parent
-      // hooks added it.
-      ::TerminateProcess(process_data.get().process_handle.get_handle(), 1);
-
-      return Error(
-          "Failed to execute Parent Hook in child '" + stringify(pid) +
-          "' with command '" + stringify(argv) + "': " +
-          parentSetup.error());
-    }
-  }
-
-  // Start child process.
-  if (::ResumeThread(process_data.get().thread_handle.get_handle()) == -1) {
-    return WindowsError(
-        "Failed to resume child process with command '" +
-        stringify(argv) + "'");
-  }
-
-  return process_data;
-}
-
-}  // namespace internal {
-}  // namespace process {
-
-#endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/3rdparty/libprocess/src/subprocess.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess.cpp b/3rdparty/libprocess/src/subprocess.cpp
index 8e1a944..b65484c 100644
--- a/3rdparty/libprocess/src/subprocess.cpp
+++ b/3rdparty/libprocess/src/subprocess.cpp
@@ -32,12 +32,6 @@
 #include <process/reap.hpp>
 #include <process/subprocess.hpp>
 
-#ifdef __WINDOWS__
-#include <process/windows/subprocess.hpp>
-#else
-#include <process/posix/subprocess.hpp>
-#endif // __WINDOWS__
-
 #include <stout/error.hpp>
 #include <stout/lambda.hpp>
 #include <stout/foreach.hpp>
@@ -46,6 +40,12 @@
 #include <stout/strings.hpp>
 #include <stout/try.hpp>
 
+#ifdef __WINDOWS__
+#include "subprocess_windows.hpp"
+#else
+#include "subprocess_posix.hpp"
+#endif // __WINDOWS__
+
 using std::map;
 using std::string;
 using std::vector;

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/3rdparty/libprocess/src/subprocess_posix.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess_posix.hpp b/3rdparty/libprocess/src/subprocess_posix.hpp
new file mode 100644
index 0000000..b478bec
--- /dev/null
+++ b/3rdparty/libprocess/src/subprocess_posix.hpp
@@ -0,0 +1,353 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+
+#ifndef __PROCESS_POSIX_SUBPROCESS_HPP__
+#define __PROCESS_POSIX_SUBPROCESS_HPP__
+
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif // __linux__
+#include <sys/types.h>
+
+#include <string>
+
+#include <glog/logging.h>
+
+#include <process/subprocess.hpp>
+
+#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>
+#include <stout/option.hpp>
+#include <stout/os.hpp>
+#include <stout/try.hpp>
+#include <stout/unreachable.hpp>
+
+#include <stout/os/close.hpp>
+#include <stout/os/environment.hpp>
+#include <stout/os/fcntl.hpp>
+#include <stout/os/signals.hpp>
+#include <stout/os/strerror.hpp>
+
+namespace process {
+namespace internal {
+
+static void close(std::initializer_list<int_fd> fds);
+
+
+static void close(
+    const Subprocess::IO::InputFileDescriptors& stdinfds,
+    const Subprocess::IO::OutputFileDescriptors& stdoutfds,
+    const Subprocess::IO::OutputFileDescriptors& stderrfds);
+
+
+inline pid_t defaultClone(const lambda::function<int()>& func)
+{
+  pid_t pid = ::fork();
+  if (pid == -1) {
+    return -1;
+  } else if (pid == 0) {
+    // Child.
+    ::exit(func());
+    UNREACHABLE();
+  } else {
+    // Parent.
+    return pid;
+  }
+}
+
+
+// This function will invoke `os::cloexec` on all specified file
+// descriptors that are valid (i.e., not `None` and >= 0).
+inline Try<Nothing> cloexec(
+    const InputFileDescriptors& stdinfds,
+    const OutputFileDescriptors& stdoutfds,
+    const OutputFileDescriptors& stderrfds)
+{
+  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) {
+    if (fd >= 0) {
+      Try<Nothing> cloexec = os::cloexec(fd);
+      if (cloexec.isError()) {
+        return Error(cloexec.error());
+      }
+    }
+  }
+
+  return Nothing();
+}
+
+
+// The main entry of the child process.
+//
+// NOTE: This function has to be async signal safe.
+inline int childMain(
+    const std::string& path,
+    char** argv,
+    char** envp,
+    const InputFileDescriptors& stdinfds,
+    const OutputFileDescriptors& stdoutfds,
+    const OutputFileDescriptors& stderrfds,
+    bool blocking,
+    int pipes[2],
+    const std::vector<Subprocess::ChildHook>& child_hooks)
+{
+  // Close parent's end of the pipes.
+  if (stdinfds.write.isSome()) {
+    ::close(stdinfds.write.get());
+  }
+  if (stdoutfds.read.isSome()) {
+    ::close(stdoutfds.read.get());
+  }
+  if (stderrfds.read.isSome()) {
+    ::close(stderrfds.read.get());
+  }
+
+  // Currently we will block the child's execution of the new process
+  // until all the parent hooks (if any) have executed.
+  if (blocking) {
+    ::close(pipes[1]);
+  }
+
+  // Redirect I/O for stdin/stdout/stderr.
+  while (::dup2(stdinfds.read, STDIN_FILENO) == -1 && errno == EINTR);
+  while (::dup2(stdoutfds.write, STDOUT_FILENO) == -1 && errno == EINTR);
+  while (::dup2(stderrfds.write, STDERR_FILENO) == -1 && errno == EINTR);
+
+  // Close the copies. We need to make sure that we do not close the
+  // file descriptor assigned to stdin/stdout/stderr in case the
+  // 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) {
+    ::close(stdinfds.read);
+  }
+  if (stdoutfds.write != STDIN_FILENO &&
+      stdoutfds.write != STDOUT_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 != stdinfds.read &&
+      stderrfds.write != stdoutfds.write) {
+    ::close(stderrfds.write);
+  }
+
+  if (blocking) {
+    // 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");
+    }
+
+    // Now close the pipe as we don't need it anymore.
+    ::close(pipes[0]);
+  }
+
+  // Run the child hooks.
+  foreach (const Subprocess::ChildHook& hook, child_hooks) {
+    Try<Nothing> callback = hook();
+
+    // If the callback failed, we should abort execution.
+    if (callback.isError()) {
+      ABORT("Failed to execute Subprocess::ChildHook: " + callback.error());
+    }
+  }
+
+  os::execvpe(path.c_str(), argv, envp);
+
+  ABORT("Failed to os::execvpe on path '" + path + "': " + os::strerror(errno));
+}
+
+
+inline Try<pid_t> cloneChild(
+    const std::string& path,
+    std::vector<std::string> argv,
+    const Option<std::map<std::string, std::string>>& environment,
+    const Option<lambda::function<
+        pid_t(const lambda::function<int()>&)>>& _clone,
+    const std::vector<Subprocess::ParentHook>& parent_hooks,
+    const std::vector<Subprocess::ChildHook>& child_hooks,
+    const InputFileDescriptors stdinfds,
+    const OutputFileDescriptors stdoutfds,
+    const OutputFileDescriptors stderrfds)
+{
+  // The real arguments that will be passed to 'os::execvpe'. We need
+  // to construct them here before doing the clone as it might not be
+  // async signal safe to perform the memory allocation.
+  char** _argv = new char*[argv.size() + 1];
+  for (size_t i = 0; i < argv.size(); i++) {
+    _argv[i] = (char*) argv[i].c_str();
+  }
+  _argv[argv.size()] = nullptr;
+
+  // Like above, we need to construct the environment that we'll pass
+  // to 'os::execvpe' as it might not be async-safe to perform the
+  // memory allocations.
+  char** envp = os::raw::environment();
+
+  if (environment.isSome()) {
+    // NOTE: We add 1 to the size for a `nullptr` terminator.
+    envp = new char*[environment.get().size() + 1];
+
+    size_t index = 0;
+    foreachpair (
+        const std::string& key,
+        const std::string& value, environment.get()) {
+      std::string entry = key + "=" + value;
+      envp[index] = new char[entry.size() + 1];
+      strncpy(envp[index], entry.c_str(), entry.size() + 1);
+      ++index;
+    }
+
+    envp[index] = nullptr;
+  }
+
+  // Determine the function to clone the child process. If the user
+  // does not specify the clone function, we will use the default.
+  lambda::function<pid_t(const lambda::function<int()>&)> clone =
+    (_clone.isSome() ? _clone.get() : defaultClone);
+
+  // Currently we will block the child's execution of the new process
+  // until all the `parent_hooks` (if any) have executed.
+  std::array<int, 2> pipes;
+  const bool blocking = !parent_hooks.empty();
+
+  if (blocking) {
+    // We assume this should not fail under reasonable conditions so we
+    // use CHECK.
+    Try<std::array<int, 2>> pipe = os::pipe();
+    CHECK_SOME(pipe);
+
+    pipes = pipe.get();
+  }
+
+  // Now, clone the child process.
+  pid_t pid = clone(lambda::bind(
+      &childMain,
+      path,
+      _argv,
+      envp,
+      stdinfds,
+      stdoutfds,
+      stderrfds,
+      blocking,
+      pipes.data(),
+      child_hooks));
+
+  delete[] _argv;
+
+  // Need to delete 'envp' if we had environment variables passed to
+  // us and we needed to allocate the space.
+  if (environment.isSome()) {
+    CHECK_NE(os::raw::environment(), envp);
+
+    // We ignore the last 'envp' entry since it is nullptr.
+    for (size_t index = 0; index < environment->size(); index++) {
+      delete[] envp[index];
+    }
+
+    delete[] envp;
+  }
+
+  if (pid == -1) {
+    // Save the errno as 'close' below might overwrite it.
+    ErrnoError error("Failed to clone");
+    internal::close(stdinfds, stdoutfds, stderrfds);
+
+    if (blocking) {
+      os::close(pipes[0]);
+      os::close(pipes[1]);
+    }
+
+    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]);
+
+    // Run the parent hooks.
+    foreach (const Subprocess::ParentHook& hook, parent_hooks) {
+      Try<Nothing> parentSetup = hook.parent_setup(pid);
+
+      // If the hook callback fails, we shouldn't proceed with the
+      // execution and hence the child process should be killed.
+      if (parentSetup.isError()) {
+        LOG(WARNING)
+          << "Failed to execute Subprocess::ParentHook in parent for child '"
+          << pid << "': " << parentSetup.error();
+
+        os::close(pipes[1]);
+
+        // Ensure the child is killed.
+        ::kill(pid, SIGKILL);
+
+        return Error(
+            "Failed to execute Subprocess::ParentHook in parent for child '" +
+            stringify(pid) + "': " + parentSetup.error());
+      }
+    }
+
+    // Now that we've executed the parent hooks, we can signal the child 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(pid, SIGKILL);
+
+      return Error("Failed to synchronize child process");
+    }
+  }
+
+  return pid;
+}
+
+}  // namespace internal {
+}  // namespace process {
+
+#endif // __PROCESS_POSIX_SUBPROCESS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c35293ef/3rdparty/libprocess/src/subprocess_windows.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess_windows.hpp b/3rdparty/libprocess/src/subprocess_windows.hpp
new file mode 100644
index 0000000..0183bb4
--- /dev/null
+++ b/3rdparty/libprocess/src/subprocess_windows.hpp
@@ -0,0 +1,102 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+
+#ifndef __PROCESS_WINDOWS_SUBPROCESS_HPP__
+#define __PROCESS_WINDOWS_SUBPROCESS_HPP__
+
+#include <signal.h>
+
+#include <string>
+#include <tuple>
+
+#include <glog/logging.h>
+
+#include <process/subprocess.hpp>
+
+#include <stout/error.hpp>
+#include <stout/foreach.hpp>
+#include <stout/hashset.hpp>
+#include <stout/option.hpp>
+#include <stout/os.hpp>
+#include <stout/os/shell.hpp>
+#include <stout/try.hpp>
+#include <stout/windows.hpp>
+
+#include <stout/os/close.hpp>
+#include <stout/os/environment.hpp>
+
+#include <userEnv.h>
+
+namespace process {
+namespace internal {
+
+// NOTE: We are expecting that components of `argv` that need to be quoted
+// (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
+// to have been already quoted correctly before we generate `command`.
+// Incorrectly-quoted command arguments will probably lead the child process
+// to terminate with an error. See also NOTE on `process::subprocess`.
+inline Try<::internal::windows::ProcessData> createChildProcess(
+    const std::string& path,
+    const std::vector<std::string>& argv,
+    const Option<std::map<std::string, std::string>>& environment,
+    const std::vector<Subprocess::ParentHook>& parent_hooks,
+    const InputFileDescriptors stdinfds,
+    const OutputFileDescriptors stdoutfds,
+    const OutputFileDescriptors stderrfds)
+{
+  Try<::internal::windows::ProcessData> process_data =
+    ::internal::windows::create_process(
+        path,
+        argv,
+        environment,
+        true, // Create suspended.
+        std::make_tuple(stdinfds.read, stdoutfds.write, stderrfds.write));
+
+  if (process_data.isError()) {
+    return process_data;
+  }
+
+  // Run the parent hooks.
+  const pid_t pid = process_data.get().pid;
+  foreach (const Subprocess::ParentHook& hook, parent_hooks) {
+    Try<Nothing> parentSetup = hook.parent_setup(pid);
+
+    // If the hook callback fails, we shouldn't proceed with the
+    // execution and hence the child process should be killed.
+    if (parentSetup.isError()) {
+      // Attempt to kill the process. Since it is still in suspended state, we
+      // do not need to kill any descendents. We also can't use `os::kill_job`
+      // because this process is not in a Job Object unless one of the parent
+      // hooks added it.
+      ::TerminateProcess(process_data.get().process_handle.get_handle(), 1);
+
+      return Error(
+          "Failed to execute Parent Hook in child '" + stringify(pid) +
+          "' with command '" + stringify(argv) + "': " +
+          parentSetup.error());
+    }
+  }
+
+  // Start child process.
+  if (::ResumeThread(process_data.get().thread_handle.get_handle()) == -1) {
+    return WindowsError(
+        "Failed to resume child process with command '" +
+        stringify(argv) + "'");
+  }
+
+  return process_data;
+}
+
+}  // namespace internal {
+}  // namespace process {
+
+#endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__


[2/4] mesos git commit: Made platform-dependent subprocess helpers internal.

Posted by gr...@apache.org.
Made platform-dependent subprocess helpers internal.

Remove platform-dependent subprocess helper code from the public
header file so that clients don't have to pay the cost of importing
the unnecessary definitions.

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


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

Branch: refs/heads/master
Commit: e38ed106946ac99faa8a94ee4daa5495205029f5
Parents: c486544
Author: James Peach <jp...@apache.org>
Authored: Wed Jul 12 17:01:13 2017 -0700
Committer: Greg Mann <gr...@gmail.com>
Committed: Wed Jul 12 17:01:13 2017 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/Makefile.am         |  6 ++--
 .../include/process/posix/subprocess.hpp        | 21 ++++++------
 .../libprocess/include/process/subprocess.hpp   |  6 ----
 .../include/process/subprocess_base.hpp         | 32 -----------------
 3rdparty/libprocess/src/subprocess.cpp          | 36 +++++++++++++++++++-
 5 files changed, 49 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/e38ed106/3rdparty/libprocess/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/Makefile.am b/3rdparty/libprocess/include/Makefile.am
index 6322815..e6aebf0 100644
--- a/3rdparty/libprocess/include/Makefile.am
+++ b/3rdparty/libprocess/include/Makefile.am
@@ -48,7 +48,6 @@ nobase_include_HEADERS =		\
   process/metrics/metric.hpp		\
   process/metrics/metrics.hpp		\
   process/metrics/timer.hpp		\
-  process/posix/subprocess.hpp		\
   process/network.hpp			\
   process/once.hpp			\
   process/owned.hpp			\
@@ -72,5 +71,8 @@ nobase_include_HEADERS =		\
   process/time.hpp			\
   process/timeout.hpp			\
   process/timer.hpp			\
-  process/timeseries.hpp		\
+  process/timeseries.hpp
+
+noinst_HEADERS = 			\
+  process/posix/subprocess.hpp		\
   process/windows/subprocess.hpp

http://git-wip-us.apache.org/repos/asf/mesos/blob/e38ed106/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 a5d10ce..b478bec 100644
--- a/3rdparty/libprocess/include/process/posix/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/posix/subprocess.hpp
@@ -43,6 +43,16 @@
 #include <stout/os/strerror.hpp>
 
 namespace process {
+namespace internal {
+
+static void close(std::initializer_list<int_fd> fds);
+
+
+static void close(
+    const Subprocess::IO::InputFileDescriptors& stdinfds,
+    const Subprocess::IO::OutputFileDescriptors& stdoutfds,
+    const Subprocess::IO::OutputFileDescriptors& stderrfds);
+
 
 inline pid_t defaultClone(const lambda::function<int()>& func)
 {
@@ -60,8 +70,6 @@ inline pid_t defaultClone(const lambda::function<int()>& func)
 }
 
 
-namespace internal {
-
 // This function will invoke `os::cloexec` on all specified file
 // descriptors that are valid (i.e., not `None` and >= 0).
 inline Try<Nothing> cloexec(
@@ -91,15 +99,6 @@ inline Try<Nothing> cloexec(
 }
 
 
-inline void signalHandler(int signal)
-{
-  // Send SIGKILL to every process in the process group of the
-  // calling process.
-  kill(0, SIGKILL);
-  abort();
-}
-
-
 // The main entry of the child process.
 //
 // NOTE: This function has to be async signal safe.

http://git-wip-us.apache.org/repos/asf/mesos/blob/e38ed106/3rdparty/libprocess/include/process/subprocess.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/subprocess.hpp b/3rdparty/libprocess/include/process/subprocess.hpp
index 106798d..e259ac0 100644
--- a/3rdparty/libprocess/include/process/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/subprocess.hpp
@@ -17,10 +17,4 @@
 // include the platform-dependent versions of the headers.
 #include <process/subprocess_base.hpp>
 
-#ifndef __WINDOWS__
-#include <process/posix/subprocess.hpp>
-#else
-#include <process/windows/subprocess.hpp>
-#endif // __WINDOWS__
-
 #endif // __PROCESS_SUBPROCESS_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/e38ed106/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 d33be2b..898ce94 100644
--- a/3rdparty/libprocess/include/process/subprocess_base.hpp
+++ b/3rdparty/libprocess/include/process/subprocess_base.hpp
@@ -13,12 +13,8 @@
 #ifndef __PROCESS_SUBPROCESS_BASE_HPP__
 #define __PROCESS_SUBPROCESS_BASE_HPP__
 
-#include <sys/types.h>
-
-#include <initializer_list>
 #include <map>
 #include <memory>
-#include <mutex>
 #include <string>
 #include <vector>
 
@@ -434,34 +430,6 @@ inline Try<Subprocess> subprocess(
       child_hooks);
 }
 
-namespace internal {
-
-inline void close(std::initializer_list<int_fd> fds)
-{
-  foreach (int_fd 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(
-    const Subprocess::IO::InputFileDescriptors& stdinfds,
-    const Subprocess::IO::OutputFileDescriptors& stdoutfds,
-    const Subprocess::IO::OutputFileDescriptors& stderrfds)
-{
-  close(
-      {stdinfds.read,
-       stdinfds.write.getOrElse(-1),
-       stdoutfds.read.getOrElse(-1),
-       stdoutfds.write,
-       stderrfds.read.getOrElse(-1),
-       stderrfds.write});
-}
-
-} // namespace internal {
 } // namespace process {
 
 #endif // __PROCESS_SUBPROCESS_BASE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/e38ed106/3rdparty/libprocess/src/subprocess.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/subprocess.cpp b/3rdparty/libprocess/src/subprocess.cpp
index 8f8a715..8e1a944 100644
--- a/3rdparty/libprocess/src/subprocess.cpp
+++ b/3rdparty/libprocess/src/subprocess.cpp
@@ -23,6 +23,7 @@
 #endif // __linux__
 #include <sys/types.h>
 
+#include <initializer_list>
 #include <string>
 
 #include <glog/logging.h>
@@ -31,6 +32,12 @@
 #include <process/reap.hpp>
 #include <process/subprocess.hpp>
 
+#ifdef __WINDOWS__
+#include <process/windows/subprocess.hpp>
+#else
+#include <process/posix/subprocess.hpp>
+#endif // __WINDOWS__
+
 #include <stout/error.hpp>
 #include <stout/lambda.hpp>
 #include <stout/foreach.hpp>
@@ -110,7 +117,7 @@ Subprocess::ChildHook Subprocess::ChildHook::UNSET_CLOEXEC(int fd)
 
 
 #ifdef __linux__
-inline void signalHandler(int signal)
+static void signalHandler(int signal)
 {
   // Send SIGKILL to every process in the process group of the
   // calling process.
@@ -266,6 +273,33 @@ static void cleanup(
   delete promise;
 }
 
+
+static void close(std::initializer_list<int_fd> fds)
+{
+  foreach (int_fd 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).
+static void close(
+    const Subprocess::IO::InputFileDescriptors& stdinfds,
+    const Subprocess::IO::OutputFileDescriptors& stdoutfds,
+    const Subprocess::IO::OutputFileDescriptors& stderrfds)
+{
+  close(
+      {stdinfds.read,
+       stdinfds.write.getOrElse(-1),
+       stdoutfds.read.getOrElse(-1),
+       stdoutfds.write,
+       stderrfds.read.getOrElse(-1),
+       stderrfds.write});
+}
+
 }  // namespace internal {