From 80021094b74b2c1c4976d4add174967041acb96d Mon Sep 17 00:00:00 2001 From: Samuel Leathers Date: Sun, 17 Sep 2017 23:31:18 -0400 Subject: [PATCH] mesos: 1.1.1 -> 1.4.0 (cherry picked from commit 6acc4084afec6bdfa4ebaf848ee53da68fc22f05) --- .../networking/cluster/mesos/default.nix | 33 +- .../cluster/mesos/fetch-mesos-deps.sh | 10 +- .../networking/cluster/mesos/mesos-deps.nix | 2 +- .../networking/cluster/mesos/nixos.patch | 374 +++++++++--------- 4 files changed, 198 insertions(+), 221 deletions(-) diff --git a/pkgs/applications/networking/cluster/mesos/default.nix b/pkgs/applications/networking/cluster/mesos/default.nix index 0506f7c154d..712b1376845 100644 --- a/pkgs/applications/networking/cluster/mesos/default.nix +++ b/pkgs/applications/networking/cluster/mesos/default.nix @@ -1,9 +1,9 @@ -{ stdenv, lib, makeWrapper, fetchurl, curl, sasl, openssh, autoconf -, automake, libtool, unzip, gnutar, jdk, maven, python, wrapPython +{ stdenv, lib, makeWrapper, fetchurl, curl, sasl, openssh +, unzip, gnutar, jdk, python, wrapPython , setuptools, boto, pythonProtobuf, apr, subversion, gzip, systemd , leveldb, glog, perf, utillinux, libnl, iproute, openssl, libevent -, ethtool, coreutils, which, iptables -, bash +, ethtool, coreutils, which, iptables, maven +, bash, autoreconfHook }: let @@ -21,7 +21,7 @@ let }); in stdenv.mkDerivation rec { - version = "1.1.1"; + version = "1.4.0"; name = "mesos-${version}"; enableParallelBuilding = true; @@ -29,7 +29,7 @@ in stdenv.mkDerivation rec { src = fetchurl { url = "mirror://apache/mesos/${version}/${name}.tar.gz"; - sha256 = "0f46ebb130d2d4a9732f95d0a71d80c8c5967f3c172b110f2ece316e05922115"; + sha256 = "0c08kd226nrjwm2z2drpq4vi97h9r8b1xkdvkgh1114fxg7cyvys"; }; patches = [ @@ -40,11 +40,13 @@ in stdenv.mkDerivation rec { # see https://github.com/cstrahan/mesos/tree/nixos-${version} ./nixos.patch ]; - + nativeBuildInputs = [ + autoreconfHook + ]; buildInputs = [ - makeWrapper autoconf automake libtool curl sasl jdk maven + makeWrapper curl sasl jdk python wrapPython boto setuptools leveldb - subversion apr glog openssl libevent + subversion apr glog openssl libevent maven ] ++ lib.optionals stdenv.isLinux [ libnl ]; @@ -52,10 +54,6 @@ in stdenv.mkDerivation rec { propagatedBuildInputs = [ pythonProtobuf ]; - - # note that we *must* statically link libprotobuf. - # if we dynamically link the lib, we get these errors: - # https://github.com/NixOS/nixpkgs/pull/19064#issuecomment-255082684 preConfigure = '' # https://issues.apache.org/jira/browse/MESOS-6616 configureFlagsArray+=( @@ -66,13 +64,10 @@ in stdenv.mkDerivation rec { # instead of sed 1i'#include ' -i src/linux/fs.cpp sed 1i'#include ' -i src/slave/containerizer/mesos/isolators/gpu/isolator.cpp - substituteInPlace 3rdparty/stout/include/stout/os/posix/chown.hpp \ --subst-var-by chown ${coreutils}/bin/chown substituteInPlace 3rdparty/stout/Makefile.am \ - --replace "-lprotobuf" \ - "${pythonProtobuf.protobuf}/lib/libprotobuf.so" substituteInPlace 3rdparty/stout/include/stout/os/posix/fork.hpp \ --subst-var-by sh ${bash}/bin/bash @@ -99,8 +94,6 @@ in stdenv.mkDerivation rec { --subst-var-by mesos-resolve $out/bin/mesos-resolve substituteInPlace src/python/native_common/ext_modules.py.in \ - --replace "-lprotobuf" \ - "${pythonProtobuf.protobuf}/lib/libprotobuf.so" substituteInPlace src/slave/containerizer/mesos/isolators/gpu/volume.cpp \ --subst-var-by cp ${coreutils}/bin/cp \ @@ -124,8 +117,6 @@ in stdenv.mkDerivation rec { substituteInPlace src/Makefile.am \ --subst-var-by mavenRepo ${mavenRepo} \ - --replace "-lprotobuf" \ - "${pythonProtobuf.protobuf}/lib/libprotobuf.so" '' + lib.optionalString stdenv.isLinux '' @@ -179,7 +170,7 @@ in stdenv.mkDerivation rec { "--enable-libevent" "--with-libevent=${libevent.dev}" "--with-protobuf=${pythonProtobuf.protobuf}" - "PROTOBUF_JAR=${mavenRepo}/com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar" + "PROTOBUF_JAR=${mavenRepo}/com/google/protobuf/protobuf-java/3.3.0/protobuf-java-3.3.0.jar" ] ++ lib.optionals stdenv.isLinux [ "--with-network-isolator" "--with-nl=${libnl.dev}" diff --git a/pkgs/applications/networking/cluster/mesos/fetch-mesos-deps.sh b/pkgs/applications/networking/cluster/mesos/fetch-mesos-deps.sh index f4a4588dbe4..cf7318ecb27 100644 --- a/pkgs/applications/networking/cluster/mesos/fetch-mesos-deps.sh +++ b/pkgs/applications/networking/cluster/mesos/fetch-mesos-deps.sh @@ -1127,10 +1127,12 @@ fetchArtifact org/vafer/jdependency/0.7/jdependency-0.7.pom fetchArtifact org/vafer/jdependency/0.7/jdependency-0.7.pom.sha1 fetchArtifact org/vafer/jdependency/0.7/jdependency-0.7.jar fetchArtifact org/vafer/jdependency/0.7/jdependency-0.7.jar.sha1 -fetchArtifact com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.pom -fetchArtifact com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.pom.sha1 -fetchArtifact com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar -fetchArtifact com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar.sha1 +fetchArtifact com/google/protobuf/protobuf-java/3.3.0/protobuf-java-3.3.0.pom +fetchArtifact com/google/protobuf/protobuf-java/3.3.0/protobuf-java-3.3.0.pom.sha1 +fetchArtifact com/google/protobuf/protobuf-java/3.3.0/protobuf-java-3.3.0.jar +fetchArtifact com/google/protobuf/protobuf-java/3.3.0/protobuf-java-3.3.0.jar.sha1 +fetchArtifact com/google/protobuf/protobuf-parent/3.3.0/protobuf-parent-3.3.0.pom +fetchArtifact com/google/protobuf/protobuf-parent/3.3.0/protobuf-parent-3.3.0.pom.sha1 fetchArtifact com/google/google/1/google-1.pom fetchArtifact com/google/google/1/google-1.pom.sha1 fetchArtifact com/google/guava/guava/11.0.2/guava-11.0.2.pom diff --git a/pkgs/applications/networking/cluster/mesos/mesos-deps.nix b/pkgs/applications/networking/cluster/mesos/mesos-deps.nix index 1edb4a755d8..642c660edb6 100644 --- a/pkgs/applications/networking/cluster/mesos/mesos-deps.nix +++ b/pkgs/applications/networking/cluster/mesos/mesos-deps.nix @@ -6,7 +6,7 @@ stdenv.mkDerivation { outputHashAlgo = "sha256"; outputHashMode = "recursive"; - outputHash = "066ikswavq3l37x1s3pfdncyj77pvpa0kj14ax5dqb9njmsg0s11"; + outputHash = "10h0qs7svw0cqjkyxs8z6s3qraa8ga920zfrr59rdlanbwg4klly"; buildInputs = [ curl ]; diff --git a/pkgs/applications/networking/cluster/mesos/nixos.patch b/pkgs/applications/networking/cluster/mesos/nixos.patch index 78e374b8d6b..a6fea024b08 100644 --- a/pkgs/applications/networking/cluster/mesos/nixos.patch +++ b/pkgs/applications/networking/cluster/mesos/nixos.patch @@ -1,20 +1,7 @@ -diff --git a/3rdparty/stout/include/stout/os/posix/chown.hpp b/3rdparty/stout/include/stout/os/posix/chown.hpp -index c82e2e574..15d332107 100644 ---- a/3rdparty/stout/include/stout/os/posix/chown.hpp -+++ b/3rdparty/stout/include/stout/os/posix/chown.hpp -@@ -34,7 +34,7 @@ inline Try chown( - // TODO(bmahler): Consider walking the file tree instead. We would need - // to be careful to not miss dotfiles. - std::string command = -- "chown -R " + stringify(uid) + ':' + stringify(gid) + " '" + path + "'"; -+ "@chown@ -R " + stringify(uid) + ':' + stringify(gid) + " '" + path + "'"; - - int status = os::system(command); - if (status != 0) { -diff --git a/3rdparty/stout/include/stout/os/posix/fork.hpp b/3rdparty/stout/include/stout/os/posix/fork.hpp -index a29967dcb..290b98b50 100644 ---- a/3rdparty/stout/include/stout/os/posix/fork.hpp -+++ b/3rdparty/stout/include/stout/os/posix/fork.hpp +diff --git i/3rdparty/stout/include/stout/os/posix/fork.hpp w/3rdparty/stout/include/stout/os/posix/fork.hpp +index a29967d..290b98b 100644 +--- i/3rdparty/stout/include/stout/os/posix/fork.hpp ++++ w/3rdparty/stout/include/stout/os/posix/fork.hpp @@ -369,7 +369,7 @@ private: if (exec.isSome()) { // Execute the command (via '/bin/sh -c command'). @@ -24,11 +11,11 @@ index a29967dcb..290b98b50 100644 EXIT(EXIT_FAILURE) << "Failed to execute '" << command << "': " << os::strerror(errno); } else if (wait.isSome()) { -diff --git a/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/stout/include/stout/posix/os.hpp -index c37e64db6..d3d87b7f0 100644 ---- a/3rdparty/stout/include/stout/posix/os.hpp -+++ b/3rdparty/stout/include/stout/posix/os.hpp -@@ -375,7 +375,7 @@ inline Option getenv(const std::string& key) +diff --git i/3rdparty/stout/include/stout/posix/os.hpp w/3rdparty/stout/include/stout/posix/os.hpp +index 8511dfd..1e7be01 100644 +--- i/3rdparty/stout/include/stout/posix/os.hpp ++++ w/3rdparty/stout/include/stout/posix/os.hpp +@@ -366,7 +366,7 @@ inline Try> pids(Option group, Option session) inline Try tar(const std::string& path, const std::string& archive) { Try tarOut = @@ -37,11 +24,11 @@ index c37e64db6..d3d87b7f0 100644 if (tarOut.isError()) { return Error("Failed to archive " + path + ": " + tarOut.error()); -diff --git a/src/Makefile.am b/src/Makefile.am -index 3bcc0f2df..e5cbc57e8 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -1545,7 +1545,7 @@ if HAS_JAVA +diff --git i/src/Makefile.am w/src/Makefile.am +index 68fff14..c572f92 100644 +--- i/src/Makefile.am ++++ w/src/Makefile.am +@@ -1775,7 +1775,7 @@ if HAS_JAVA $(MESOS_JAR): $(MESOS_JAR_SOURCE) $(MESOS_JAR_GENERATED) java/mesos.pom @echo "Building mesos-$(PACKAGE_VERSION).jar ..." @@ -50,10 +37,10 @@ index 3bcc0f2df..e5cbc57e8 100644 # Convenience library for JNI bindings. # TODO(Charles Reiss): We really should be building the Java library -diff --git a/src/cli/mesos-scp b/src/cli/mesos-scp -index a71ab0708..1043d1b3c 100755 ---- a/src/cli/mesos-scp -+++ b/src/cli/mesos-scp +diff --git i/src/cli/mesos-scp w/src/cli/mesos-scp +index a71ab07..1043d1b 100755 +--- i/src/cli/mesos-scp ++++ w/src/cli/mesos-scp @@ -19,7 +19,8 @@ if sys.version_info < (2,6,0): @@ -64,11 +51,11 @@ index a71ab0708..1043d1b3c 100755 try: process = subprocess.Popen( cmd, -diff --git a/src/common/command_utils.cpp b/src/common/command_utils.cpp -index 09e805140..90bf65896 100644 ---- a/src/common/command_utils.cpp -+++ b/src/common/command_utils.cpp -@@ -140,7 +140,7 @@ Future tar( +diff --git i/src/common/command_utils.cpp w/src/common/command_utils.cpp +index c50be76..388cc53 100644 +--- i/src/common/command_utils.cpp ++++ w/src/common/command_utils.cpp +@@ -142,7 +142,7 @@ Future tar( argv.emplace_back(input); @@ -77,7 +64,7 @@ index 09e805140..90bf65896 100644 .then([]() { return Nothing(); }); } -@@ -162,7 +162,7 @@ Future untar( +@@ -164,7 +164,7 @@ Future untar( argv.emplace_back(directory.get()); } @@ -86,7 +73,7 @@ index 09e805140..90bf65896 100644 .then([]() { return Nothing(); }); } -@@ -170,7 +170,7 @@ Future untar( +@@ -172,7 +172,7 @@ Future untar( Future sha512(const Path& input) { #ifdef __linux__ @@ -95,7 +82,7 @@ index 09e805140..90bf65896 100644 vector argv = { cmd, input // Input file to compute shasum. -@@ -206,7 +206,7 @@ Future gzip(const Path& input) +@@ -208,7 +208,7 @@ Future gzip(const Path& input) input }; @@ -104,7 +91,7 @@ index 09e805140..90bf65896 100644 .then([]() { return Nothing(); }); } -@@ -219,7 +219,7 @@ Future decompress(const Path& input) +@@ -221,7 +221,7 @@ Future decompress(const Path& input) input }; @@ -113,41 +100,45 @@ index 09e805140..90bf65896 100644 .then([]() { return Nothing(); }); } -diff --git a/src/launcher/fetcher.cpp b/src/launcher/fetcher.cpp -index 4456c2813..e22c8fc03 100644 ---- a/src/launcher/fetcher.cpp -+++ b/src/launcher/fetcher.cpp -@@ -68,13 +68,13 @@ static Try extract( +diff --git i/src/launcher/fetcher.cpp w/src/launcher/fetcher.cpp +index 42980f5..3aebeed 100644 +--- i/src/launcher/fetcher.cpp ++++ w/src/launcher/fetcher.cpp +@@ -80,17 +80,17 @@ static Try extract( strings::endsWith(sourcePath, ".tar.bz2") || strings::endsWith(sourcePath, ".txz") || strings::endsWith(sourcePath, ".tar.xz")) { -- command = "tar -C '" + destinationDirectory + "' -xf"; -+ command = "@tar@ -C '" + destinationDirectory + "' -xf"; +- command = {"tar", "-C", destinationDirectory, "-xf", sourcePath}; ++ command = {"@tar@", "-C", destinationDirectory, "-xf", sourcePath}; } else if (strings::endsWith(sourcePath, ".gz")) { string pathWithoutExtension = sourcePath.substr(0, sourcePath.length() - 3); string filename = Path(pathWithoutExtension).basename(); -- command = "gzip -dc > '" + destinationDirectory + "/" + filename + "' <"; -+ command = "@gzip@ -dc > '" + destinationDirectory + "/" + filename + "' <"; + string destinationPath = path::join(destinationDirectory, filename); + +- command = {"gunzip", "-d", "-c"}; ++ command = {"@gunzip@", "-d", "-c"}; + in = Subprocess::PATH(sourcePath); + out = Subprocess::PATH(destinationPath); } else if (strings::endsWith(sourcePath, ".zip")) { -- command = "unzip -o -d '" + destinationDirectory + "'"; -+ command = "@unzip@ -o -d '" + destinationDirectory + "'"; +- command = {"unzip", "-o", "-d", destinationDirectory, sourcePath}; ++ command = {"@unzip@", "-o", "-d", destinationDirectory, sourcePath}; } else { return false; } -@@ -162,7 +162,7 @@ static Try copyFile( +@@ -193,7 +193,7 @@ static Try copyFile( const string& sourcePath, const string& destinationPath) { -- const string command = "cp '" + sourcePath + "' '" + destinationPath + "'"; -+ const string command = "@cp@ '" + sourcePath + "' '" + destinationPath + "'"; +- int status = os::spawn("cp", {"cp", sourcePath, destinationPath}); ++ int status = os::spawn("cp", {"@cp@", sourcePath, destinationPath}); - LOG(INFO) << "Copying resource with command:" << command; - -diff --git a/src/linux/perf.cpp b/src/linux/perf.cpp -index aa31982eb..8b5331b17 100644 ---- a/src/linux/perf.cpp -+++ b/src/linux/perf.cpp -@@ -127,7 +127,7 @@ private: + if (status == -1) { + return ErrnoError("Failed to copy '" + sourcePath + "'"); +diff --git i/src/linux/perf.cpp w/src/linux/perf.cpp +index b301e25..356a2cf 100644 +--- i/src/linux/perf.cpp ++++ w/src/linux/perf.cpp +@@ -128,7 +128,7 @@ private: // NOTE: The supervisor childhook places perf in its own process group // and will kill the perf process when the parent dies. Try _perf = subprocess( @@ -156,19 +147,10 @@ index aa31982eb..8b5331b17 100644 argv, Subprocess::PIPE(), Subprocess::PIPE(), -@@ -319,7 +319,7 @@ bool valid(const set& events) - ostringstream command; - - // Log everything to stderr which is then redirected to /dev/null. -- command << "perf stat --log-fd 2"; -+ command << "@perf@ stat --log-fd 2"; - foreach (const string& event, events) { - command << " --event " << event; - } -diff --git a/src/linux/systemd.cpp b/src/linux/systemd.cpp -index 6318f48fc..394d88d47 100644 ---- a/src/linux/systemd.cpp -+++ b/src/linux/systemd.cpp +diff --git i/src/linux/systemd.cpp w/src/linux/systemd.cpp +index 6318f48..394d88d 100644 +--- i/src/linux/systemd.cpp ++++ w/src/linux/systemd.cpp @@ -196,13 +196,21 @@ bool exists() // This is static as the init system should not change while we are running. static const bool exists = []() -> bool { @@ -209,10 +191,10 @@ index 6318f48fc..394d88d47 100644 Try daemonReload = os::shell("systemctl daemon-reload"); if (daemonReload.isError()) { return Error("Failed to reload systemd daemon: " + daemonReload.error()); -diff --git a/src/python/cli/src/mesos/cli.py b/src/python/cli/src/mesos/cli.py -index f342992e0..354abf443 100644 ---- a/src/python/cli/src/mesos/cli.py -+++ b/src/python/cli/src/mesos/cli.py +diff --git i/src/python/cli/src/mesos/cli.py w/src/python/cli/src/mesos/cli.py +index 4a9b558..c08a8b9 100644 +--- i/src/python/cli/src/mesos/cli.py ++++ w/src/python/cli/src/mesos/cli.py @@ -40,7 +40,7 @@ def resolve(master): import subprocess @@ -222,10 +204,10 @@ index f342992e0..354abf443 100644 stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, -diff --git a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp -index af9f3736b..f8554d414 100644 ---- a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp -+++ b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp +diff --git i/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp w/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp +index 5b630c1..d63ad69 100644 +--- i/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp ++++ w/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp @@ -499,7 +499,7 @@ Future> DockerVolumeIsolatorProcess::_prepare( // unsafe arbitrary commands). CommandInfo* command = launchInfo.add_pre_exec_commands(); @@ -235,11 +217,11 @@ index af9f3736b..f8554d414 100644 command->add_arguments("mount"); command->add_arguments("-n"); command->add_arguments("--rbind"); -diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp -index df16b8fee..4a17475bd 100644 ---- a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp -+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp -@@ -159,9 +159,9 @@ Try LinuxFilesystemIsolatorProcess::create(const Flags& flags) +diff --git i/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp w/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp +index d7fe9a8..1361a4e 100644 +--- i/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp ++++ w/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp +@@ -154,9 +154,9 @@ Try LinuxFilesystemIsolatorProcess::create(const Flags& flags) // here because 'create' will only be invoked during // initialization. Try mount = os::shell( @@ -252,7 +234,7 @@ index df16b8fee..4a17475bd 100644 workDir->c_str(), workDir->c_str(), workDir->c_str(), -@@ -180,8 +180,8 @@ Try LinuxFilesystemIsolatorProcess::create(const Flags& flags) +@@ -175,8 +175,8 @@ Try LinuxFilesystemIsolatorProcess::create(const Flags& flags) LOG(INFO) << "Making '" << workDir.get() << "' a shared mount"; Try mount = os::shell( @@ -263,7 +245,7 @@ index df16b8fee..4a17475bd 100644 workDir->c_str(), workDir->c_str()); -@@ -404,7 +404,7 @@ Try> LinuxFilesystemIsolatorProcess::getPreExecCommands( +@@ -422,7 +422,7 @@ Try> LinuxFilesystemIsolatorProcess::getPreExecCommands( CommandInfo command; command.set_shell(false); @@ -272,7 +254,7 @@ index df16b8fee..4a17475bd 100644 command.add_arguments("mount"); command.add_arguments("-n"); command.add_arguments("--rbind"); -@@ -569,7 +569,7 @@ Try> LinuxFilesystemIsolatorProcess::getPreExecCommands( +@@ -610,7 +610,7 @@ Try> LinuxFilesystemIsolatorProcess::getPreExecCommands( // TODO(jieyu): Consider the mode in the volume. CommandInfo command; command.set_shell(false); @@ -281,11 +263,11 @@ index df16b8fee..4a17475bd 100644 command.add_arguments("mount"); command.add_arguments("-n"); command.add_arguments("--rbind"); -diff --git a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp -index a1283e5ee..a918427bf 100644 ---- a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp -+++ b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp -@@ -207,7 +207,7 @@ Future> SharedFilesystemIsolatorProcess::prepare( +diff --git i/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp w/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp +index 927d95b..576dc63 100644 +--- i/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp ++++ w/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp +@@ -208,7 +208,7 @@ Future> SharedFilesystemIsolatorProcess::prepare( } launchInfo.add_pre_exec_commands()->set_value( @@ -294,11 +276,11 @@ index a1283e5ee..a918427bf 100644 } return launchInfo; -diff --git a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp -index e3756c920..cfe458b59 100644 ---- a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp -+++ b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp -@@ -355,7 +355,7 @@ Future> NvidiaGpuIsolatorProcess::_prepare( +diff --git i/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp w/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp +index 25636b5..33ec315 100644 +--- i/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp ++++ w/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp +@@ -401,7 +401,7 @@ Future> NvidiaGpuIsolatorProcess::_prepare( } launchInfo.add_pre_exec_commands()->set_value( @@ -307,11 +289,11 @@ index e3756c920..cfe458b59 100644 volume.HOST_PATH() + " " + target); } -diff --git a/src/slave/containerizer/mesos/isolators/gpu/volume.cpp b/src/slave/containerizer/mesos/isolators/gpu/volume.cpp -index 478752f37..ab527f0cd 100644 ---- a/src/slave/containerizer/mesos/isolators/gpu/volume.cpp -+++ b/src/slave/containerizer/mesos/isolators/gpu/volume.cpp -@@ -281,7 +281,7 @@ Try NvidiaVolume::create() +diff --git i/src/slave/containerizer/mesos/isolators/gpu/volume.cpp w/src/slave/containerizer/mesos/isolators/gpu/volume.cpp +index 536a3c7..e2819dd 100644 +--- i/src/slave/containerizer/mesos/isolators/gpu/volume.cpp ++++ w/src/slave/containerizer/mesos/isolators/gpu/volume.cpp +@@ -274,7 +274,7 @@ Try NvidiaVolume::create() string path = path::join(hostPath, "bin", binary); if (!os::exists(path)) { @@ -320,7 +302,7 @@ index 478752f37..ab527f0cd 100644 Try which = os::shell(command); if (which.isSome()) { -@@ -295,7 +295,7 @@ Try NvidiaVolume::create() +@@ -288,7 +288,7 @@ Try NvidiaVolume::create() : "No such file or directory")); } @@ -329,7 +311,7 @@ index 478752f37..ab527f0cd 100644 Try cp = os::shell(command); if (cp.isError()) { return Error("Failed to os::shell '" + command + "': " + cp.error()); -@@ -367,7 +367,7 @@ Try NvidiaVolume::create() +@@ -360,7 +360,7 @@ Try NvidiaVolume::create() Path(realpath.get()).basename()); if (!os::exists(libraryPath)) { @@ -338,11 +320,11 @@ index 478752f37..ab527f0cd 100644 Try cp = os::shell(command); if (cp.isError()) { return Error("Failed to os::shell '" + command + "':" -diff --git a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp -index 0d9ec57d9..a177e4476 100644 ---- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp -+++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp -@@ -94,7 +94,7 @@ Future> NamespacesPidIsolatorProcess::prepare( +diff --git i/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp w/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp +index 42bc2e1..2f9066e 100644 +--- i/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp ++++ w/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp +@@ -131,7 +131,7 @@ Future> NamespacesPidIsolatorProcess::prepare( // // TOOD(jieyu): Consider unmount the existing /proc. launchInfo.add_pre_exec_commands()->set_value( @@ -351,11 +333,11 @@ index 0d9ec57d9..a177e4476 100644 return launchInfo; } -diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp -index c87e6715a..6601cd1b3 100644 ---- a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp -+++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp -@@ -262,9 +262,9 @@ Try NetworkCniIsolatorProcess::create(const Flags& flags) +diff --git i/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp w/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp +index fc68f04..267b040 100644 +--- i/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp ++++ w/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp +@@ -205,9 +205,9 @@ Try NetworkCniIsolatorProcess::create(const Flags& flags) // here because 'create' will only be invoked during // initialization. Try mount = os::shell( @@ -368,7 +350,7 @@ index c87e6715a..6601cd1b3 100644 rootDir->c_str(), rootDir->c_str(), rootDir->c_str(), -@@ -284,8 +284,8 @@ Try NetworkCniIsolatorProcess::create(const Flags& flags) +@@ -227,8 +227,8 @@ Try NetworkCniIsolatorProcess::create(const Flags& flags) LOG(INFO) << "Making '" << rootDir.get() << "' a shared mount"; Try mount = os::shell( @@ -379,11 +361,11 @@ index c87e6715a..6601cd1b3 100644 rootDir->c_str(), rootDir->c_str()); -diff --git a/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp b/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp -index b470f0c82..6110a43ee 100644 ---- a/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp -+++ b/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp -@@ -303,7 +303,7 @@ Try PortMapper::addPortMapping( +diff --git i/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp w/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp +index 43cf3e4..94bad8b 100644 +--- i/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp ++++ w/src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp +@@ -301,7 +301,7 @@ Try PortMapper::addPortMapping( # Check if the `chain` exists in the iptable. If it does not # exist go ahead and install the chain in the iptables NAT # table. @@ -392,7 +374,7 @@ index b470f0c82..6110a43ee 100644 if [ $? -ne 0 ]; then # NOTE: When we create the chain, there is a possibility of a # race due to which a container launch can fail. This can -@@ -317,25 +317,25 @@ Try PortMapper::addPortMapping( +@@ -315,25 +315,25 @@ Try PortMapper::addPortMapping( # since it can happen only when the chain is created the first # time and two commands for creation of the chain are executed # simultaneously. @@ -422,7 +404,7 @@ index b470f0c82..6110a43ee 100644 chain, chain, chain, -@@ -362,7 +362,7 @@ Try PortMapper::delPortMapping() +@@ -360,7 +360,7 @@ Try PortMapper::delPortMapping() # The iptables command searches for the DNAT rules with tag # "container_id: ", and if it exists goes ahead # and deletes it. @@ -431,11 +413,11 @@ index b470f0c82..6110a43ee 100644 chain, getIptablesRuleTag()).get(); -diff --git a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp -index 20fb6ab35..46c160977 100644 ---- a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp -+++ b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp -@@ -1393,19 +1393,19 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) +diff --git i/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp w/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp +index 57d4ccd..68c9577 100644 +--- i/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp ++++ w/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp +@@ -1394,19 +1394,19 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) // Check the availability of a few Linux commands that we will use. // We use the blocking os::shell here because 'create' will only be // invoked during initialization. @@ -458,7 +440,7 @@ index 20fb6ab35..46c160977 100644 if (checkCommandIp.isError()) { return Error("Check command 'ip' failed: " + checkCommandIp.error()); } -@@ -1925,9 +1925,9 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) +@@ -1940,9 +1940,9 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) // visible. It's OK to use the blocking os::shell here because // 'create' will only be invoked during initialization. Try mount = os::shell( @@ -471,7 +453,7 @@ index 20fb6ab35..46c160977 100644 bindMountRoot->c_str(), bindMountRoot->c_str(), bindMountRoot->c_str(), -@@ -1944,8 +1944,8 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) +@@ -1959,8 +1959,8 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) // shared mount yet (possibly due to slave crash while preparing // the work directory mount). It's safe to re-do the following. Try mount = os::shell( @@ -482,7 +464,7 @@ index 20fb6ab35..46c160977 100644 bindMountRoot->c_str(), bindMountRoot->c_str()); -@@ -1964,8 +1964,8 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) +@@ -1979,8 +1979,8 @@ Try PortMappingIsolatorProcess::create(const Flags& flags) // so that they are in different peer groups. if (entry.shared() == bindMountEntry->shared()) { Try mount = os::shell( @@ -493,7 +475,7 @@ index 20fb6ab35..46c160977 100644 bindMountRoot->c_str(), bindMountRoot->c_str()); -@@ -3911,6 +3911,8 @@ Try PortMappingIsolatorProcess::removeHostIPFilters( +@@ -3927,6 +3927,8 @@ Try PortMappingIsolatorProcess::removeHostIPFilters( // TODO(jieyu): Use the Subcommand abstraction to remove most of the // logic here. Completely remove this function once we can assume a // newer kernel where 'setns' works for mount namespaces. @@ -502,7 +484,7 @@ index 20fb6ab35..46c160977 100644 string PortMappingIsolatorProcess::scripts(Info* info) { ostringstream script; -@@ -3921,7 +3923,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -3937,7 +3939,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) // Mark the mount point PORT_MAPPING_BIND_MOUNT_ROOT() as slave // mount so that changes in the container will not be propagated to // the host. @@ -511,7 +493,7 @@ index 20fb6ab35..46c160977 100644 // Disable IPv6 when IPv6 module is loaded as IPv6 packets won't be // forwarded anyway. -@@ -3929,7 +3931,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -3945,7 +3947,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) << " echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6\n"; // Configure lo and eth0. @@ -520,7 +502,7 @@ index 20fb6ab35..46c160977 100644 << " mtu " << hostEth0MTU << " up\n"; // NOTE: This is mostly a kernel issue: in veth_xmit() the kernel -@@ -3938,12 +3940,12 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -3954,12 +3956,12 @@ string PortMappingIsolatorProcess::scripts(Info* info) // when we receive a packet with a bad checksum. Disabling rx // checksum offloading ensures the TCP layer will checksum and drop // it. @@ -537,7 +519,7 @@ index 20fb6ab35..46c160977 100644 // Restrict the ephemeral ports that can be used by the container. script << "echo " << info->ephemeralPorts.lower() << " " -@@ -3972,19 +3974,19 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -3988,19 +3990,19 @@ string PortMappingIsolatorProcess::scripts(Info* info) } // Set up filters on lo and eth0. @@ -561,7 +543,7 @@ index 20fb6ab35..46c160977 100644 << " protocol ip" << " prio " << Priority(IP_FILTER_PRIORITY, NORMAL).get() << " u32" << " flowid ffff:0" -@@ -3995,7 +3997,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -4011,7 +4013,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) foreach (const PortRange& range, getPortRanges(info->nonEphemeralPorts + info->ephemeralPorts)) { // Local traffic inside a container will not be redirected to eth0. @@ -570,7 +552,7 @@ index 20fb6ab35..46c160977 100644 << " protocol ip" << " prio " << Priority(IP_FILTER_PRIORITY, HIGH).get() << " u32" << " flowid ffff:0" -@@ -4004,7 +4006,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -4020,7 +4022,7 @@ string PortMappingIsolatorProcess::scripts(Info* info) // Traffic going to host loopback IP and ports assigned to this // container will be redirected to lo. @@ -579,7 +561,7 @@ index 20fb6ab35..46c160977 100644 << " protocol ip" << " prio " << Priority(IP_FILTER_PRIORITY, NORMAL).get() << " u32" << " flowid ffff:0" -@@ -4016,14 +4018,14 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -4032,14 +4034,14 @@ string PortMappingIsolatorProcess::scripts(Info* info) } // Do not forward the ICMP packet if the destination IP is self. @@ -596,8 +578,8 @@ index 20fb6ab35..46c160977 100644 << " protocol ip" << " prio " << Priority(ICMP_FILTER_PRIORITY, NORMAL).get() << " u32" << " flowid ffff:0" -@@ -4032,9 +4034,9 @@ string PortMappingIsolatorProcess::scripts(Info* info) - << net::IPNetwork::LOOPBACK_V4().address() << "\n"; +@@ -4048,9 +4050,9 @@ string PortMappingIsolatorProcess::scripts(Info* info) + << net::IP::Network::LOOPBACK_V4().address() << "\n"; // Display the filters created on eth0 and lo. - script << "tc filter show dev " << eth0 @@ -608,7 +590,7 @@ index 20fb6ab35..46c160977 100644 << " parent " << ingress::HANDLE << "\n"; // If throughput limit for container egress traffic exists, use HTB -@@ -4046,9 +4048,9 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -4062,9 +4064,9 @@ string PortMappingIsolatorProcess::scripts(Info* info) // throughput. TBF requires other parameters such as 'burst' that // HTB already has default values for. if (egressRateLimitPerContainer.isSome()) { @@ -620,7 +602,7 @@ index 20fb6ab35..46c160977 100644 << CONTAINER_TX_HTB_HANDLE << " classid " << CONTAINER_TX_HTB_CLASS_ID << " htb rate " << egressRateLimitPerContainer.get().bytes() * 8 << "bit\n"; -@@ -4059,12 +4061,12 @@ string PortMappingIsolatorProcess::scripts(Info* info) +@@ -4075,12 +4077,12 @@ string PortMappingIsolatorProcess::scripts(Info* info) // fq_codel, which has a larger buffer and better control on // buffer bloat. // TODO(cwang): Verity that fq_codel qdisc is available. @@ -636,24 +618,24 @@ index 20fb6ab35..46c160977 100644 } return script.str(); -diff --git a/src/slave/containerizer/mesos/isolators/posix/disk.cpp b/src/slave/containerizer/mesos/isolators/posix/disk.cpp -index db0583386..542586370 100644 ---- a/src/slave/containerizer/mesos/isolators/posix/disk.cpp -+++ b/src/slave/containerizer/mesos/isolators/posix/disk.cpp -@@ -540,7 +540,7 @@ private: +diff --git i/src/slave/containerizer/mesos/isolators/posix/disk.cpp w/src/slave/containerizer/mesos/isolators/posix/disk.cpp +index eb23025..db268ea 100644 +--- i/src/slave/containerizer/mesos/isolators/posix/disk.cpp ++++ w/src/slave/containerizer/mesos/isolators/posix/disk.cpp +@@ -572,7 +572,7 @@ private: // NOTE: The supervisor childhook will watch the parent process and kill // the 'du' process in case that the parent die. Try s = subprocess( - "du", + "@du@", command, - Subprocess::PATH("/dev/null"), + Subprocess::PATH(os::DEV_NULL), Subprocess::PIPE(), -diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp -index 210e67ad0..60b3a15e4 100644 ---- a/src/slave/containerizer/mesos/isolators/volume/image.cpp -+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp -@@ -214,7 +214,7 @@ Future> VolumeImageIsolatorProcess::_prepare( +diff --git i/src/slave/containerizer/mesos/isolators/volume/image.cpp w/src/slave/containerizer/mesos/isolators/volume/image.cpp +index 35966aa..b62fc86 100644 +--- i/src/slave/containerizer/mesos/isolators/volume/image.cpp ++++ w/src/slave/containerizer/mesos/isolators/volume/image.cpp +@@ -231,7 +231,7 @@ Future> VolumeImageIsolatorProcess::_prepare( CommandInfo* command = launchInfo.add_pre_exec_commands(); command->set_shell(false); @@ -662,11 +644,11 @@ index 210e67ad0..60b3a15e4 100644 command->add_arguments("mount"); command->add_arguments("-n"); command->add_arguments("--rbind"); -diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp -index 7b976d292..474dcd486 100644 ---- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp -+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp -@@ -240,7 +240,7 @@ Future> VolumeSandboxPathIsolatorProcess::prepare( +diff --git i/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp w/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp +index b321b86..8ed3e78 100644 +--- i/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp ++++ w/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp +@@ -265,7 +265,7 @@ Future> VolumeSandboxPathIsolatorProcess::prepare( CommandInfo* command = launchInfo.add_pre_exec_commands(); command->set_shell(false); @@ -675,58 +657,60 @@ index 7b976d292..474dcd486 100644 command->add_arguments("mount"); command->add_arguments("-n"); command->add_arguments("--rbind"); -diff --git a/src/slave/containerizer/mesos/provisioner/backends/copy.cpp b/src/slave/containerizer/mesos/provisioner/backends/copy.cpp -index 9c5354e5f..a73a9692e 100644 ---- a/src/slave/containerizer/mesos/provisioner/backends/copy.cpp -+++ b/src/slave/containerizer/mesos/provisioner/backends/copy.cpp -@@ -147,7 +147,7 @@ Future CopyBackendProcess::_provision( +diff --git i/src/slave/containerizer/mesos/provisioner/backends/copy.cpp w/src/slave/containerizer/mesos/provisioner/backends/copy.cpp +index 69faa03..01a3ed6 100644 +--- i/src/slave/containerizer/mesos/provisioner/backends/copy.cpp ++++ w/src/slave/containerizer/mesos/provisioner/backends/copy.cpp +@@ -266,7 +266,7 @@ Future CopyBackendProcess::_provision( #endif // __APPLE__ || __FreeBSD__ Try s = subprocess( - "cp", + "@cp@", args, - Subprocess::PATH("/dev/null"), - Subprocess::PATH("/dev/null"), -@@ -180,7 +180,7 @@ Future CopyBackendProcess::destroy(const string& rootfs) + Subprocess::PATH(os::DEV_NULL), + Subprocess::PATH(os::DEV_NULL), +@@ -313,7 +313,7 @@ Future CopyBackendProcess::destroy(const string& rootfs) vector argv{"rm", "-rf", rootfs}; Try s = subprocess( - "rm", + "@rm@", argv, - Subprocess::PATH("/dev/null"), + Subprocess::PATH(os::DEV_NULL), Subprocess::FD(STDOUT_FILENO), -diff --git a/src/uri/fetchers/copy.cpp b/src/uri/fetchers/copy.cpp -index 2cfef5ab0..8a62f7699 100644 ---- a/src/uri/fetchers/copy.cpp -+++ b/src/uri/fetchers/copy.cpp -@@ -97,7 +97,7 @@ Future CopyFetcherPlugin::fetch( - const vector argv = {"cp", "-a", uri.path(), directory}; +diff --git i/src/uri/fetchers/copy.cpp w/src/uri/fetchers/copy.cpp +index 17f69be..831b08a 100644 +--- i/src/uri/fetchers/copy.cpp ++++ w/src/uri/fetchers/copy.cpp +@@ -97,8 +97,8 @@ Future CopyFetcherPlugin::fetch( + VLOG(1) << "Copying '" << uri.path() << "' to '" << directory << "'"; - Try s = subprocess( -- "cp", -+ "@cp@", - argv, - Subprocess::PATH("/dev/null"), - Subprocess::PIPE(), -diff --git a/src/uri/fetchers/curl.cpp b/src/uri/fetchers/curl.cpp -index 7b746d619..12bbb04df 100644 ---- a/src/uri/fetchers/curl.cpp -+++ b/src/uri/fetchers/curl.cpp -@@ -107,7 +107,7 @@ Future CurlFetcherPlugin::fetch( + #ifndef __WINDOWS__ +- const char* copyCommand = "cp"; +- const vector argv = {"cp", "-a", uri.path(), directory}; ++ const char* copyCommand = "@cp@"; ++ const vector argv = {"@cp@", "-a", uri.path(), directory}; + #else // __WINDOWS__ + const char* copyCommand = os::Shell::name; + const vector argv = +diff --git i/src/uri/fetchers/curl.cpp w/src/uri/fetchers/curl.cpp +index f34daf2..6a50341 100644 +--- i/src/uri/fetchers/curl.cpp ++++ w/src/uri/fetchers/curl.cpp +@@ -109,7 +109,7 @@ Future CurlFetcherPlugin::fetch( }; Try s = subprocess( - "curl", + "@curl@", argv, - Subprocess::PATH("/dev/null"), + Subprocess::PATH(os::DEV_NULL), Subprocess::PIPE(), -diff --git a/src/uri/fetchers/docker.cpp b/src/uri/fetchers/docker.cpp -index 3f38dddfb..fd991ee74 100644 ---- a/src/uri/fetchers/docker.cpp -+++ b/src/uri/fetchers/docker.cpp +diff --git i/src/uri/fetchers/docker.cpp w/src/uri/fetchers/docker.cpp +index 91db13b..82a7fc4 100644 +--- i/src/uri/fetchers/docker.cpp ++++ w/src/uri/fetchers/docker.cpp @@ -114,7 +114,7 @@ static Future curl( // TODO(jieyu): Kill the process if discard is called. @@ -734,14 +718,14 @@ index 3f38dddfb..fd991ee74 100644 - "curl", + "@curl@", argv, - Subprocess::PATH("/dev/null"), + Subprocess::PATH(os::DEV_NULL), Subprocess::PIPE(), -@@ -213,7 +213,7 @@ static Future download( +@@ -229,7 +229,7 @@ static Future download( // TODO(jieyu): Kill the process if discard is called. Try s = subprocess( - "curl", + "@curl@", argv, - Subprocess::PATH("/dev/null"), + Subprocess::PATH(os::DEV_NULL), Subprocess::PIPE(),