summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorCharles Strahan <charles@cstrahan.com>2016-12-28 00:19:51 -0500
committerCharles Strahan <charles@cstrahan.com>2016-12-29 20:09:46 -0500
commit7ebcada02028e5ce8199cc123fda6aa1aba72e64 (patch)
treefc4a4c2c31aeddf0625593ee5be48caa30741d4f /pkgs
parentda70d3da0f11b22eac77756b39b349215e06b2e3 (diff)
downloadnixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar.gz
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar.bz2
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar.lz
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar.xz
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.tar.zst
nixpkgs-7ebcada02028e5ce8199cc123fda6aa1aba72e64.zip
mesos: 1.0.1 -> 1.1.0
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/applications/networking/cluster/mesos/default.nix94
-rw-r--r--pkgs/applications/networking/cluster/mesos/maven_repo.patch13
-rw-r--r--pkgs/applications/networking/cluster/mesos/nixos.patch444
-rw-r--r--pkgs/applications/networking/cluster/mesos/rb36610.patch7
-rw-r--r--pkgs/applications/networking/cluster/mesos/rb51324.patch71
-rw-r--r--pkgs/applications/networking/cluster/mesos/rb51325.patch157
-rw-r--r--pkgs/development/interpreters/python/build-python-package-setuptools.nix2
-rw-r--r--pkgs/development/libraries/protobuf/generic.nix22
-rw-r--r--pkgs/top-level/python-packages.nix23
9 files changed, 484 insertions, 349 deletions
diff --git a/pkgs/applications/networking/cluster/mesos/default.nix b/pkgs/applications/networking/cluster/mesos/default.nix
index 8857e6ba4e3..818848f6a7f 100644
--- a/pkgs/applications/networking/cluster/mesos/default.nix
+++ b/pkgs/applications/networking/cluster/mesos/default.nix
@@ -2,16 +2,27 @@
 , automake115x, libtool, unzip, gnutar, jdk, maven, python, wrapPython
 , setuptools, boto, pythonProtobuf, apr, subversion, gzip, systemd
 , leveldb, glog, perf, utillinux, libnl, iproute, openssl, libevent
-, ethtool, coreutils
+, ethtool, coreutils, which, iptables
 , bash
 }:
 
 let
   mavenRepo = import ./mesos-deps.nix { inherit stdenv curl; };
   soext = if stdenv.system == "x86_64-darwin" then "dylib" else "so";
+  # `tar -z` requires gzip on $PATH, so wrap tar.
+  # At some point, we should try to patch mesos so we add gzip to the PATH when
+  # tar is invoked. I think that only needs to be done here:
+  #   src/common/command_utils.cpp
+  # https://github.com/NixOS/nixpkgs/issues/13783
+  tarWithGzip = lib.overrideDerivation gnutar (oldAttrs: {
+    buildInputs = (oldAttrs.buildInputs or []) ++ [ makeWrapper ];
+    postInstall = (oldAttrs.postInstall or "") + ''
+      wrapProgram $out/bin/tar --prefix PATH ":" "${gzip}/bin"
+    '';
+  });
 
 in stdenv.mkDerivation rec {
-  version = "1.0.1";
+  version = "1.1.0";
   name = "mesos-${version}";
 
   enableParallelBuilding = true;
@@ -19,17 +30,14 @@ in stdenv.mkDerivation rec {
 
   src = fetchurl {
     url = "mirror://apache/mesos/${version}/${name}.tar.gz";
-    sha256 = "1hdh2wh11ck98ycfrxfzgivgk2pjl3638vkyw14xj7faj9qxjlz0";
+    sha256 = "1hdjd4syyp88l0bnh88bhzvn9466ad2ysfp9pq3kwj3qzwg5jv8g";
   };
 
   patches = [
     # https://reviews.apache.org/r/36610/
+    # TODO: is this still needed?
     ./rb36610.patch
 
-    # https://issues.apache.org/jira/browse/MESOS-6013
-    ./rb51324.patch
-    ./rb51325.patch
-
     # see https://github.com/cstrahan/mesos/tree/nixos-${version}
     ./nixos.patch
   ];
@@ -46,33 +54,55 @@ in stdenv.mkDerivation rec {
     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 = ''
-    substituteInPlace 3rdparty/stout/include/stout/os/posix/fork.hpp \
-      --subst-var-by sh ${bash}/bin/bash
+    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}/lib/libprotobuf.a"
 
-    substituteInPlace 3rdparty/stout/include/stout/os/posix/shell.hpp \
+    substituteInPlace 3rdparty/stout/include/stout/os/posix/fork.hpp \
       --subst-var-by sh ${bash}/bin/bash
 
-    substituteInPlace src/Makefile.am \
-      --subst-var-by mavenRepo ${mavenRepo}
+    substituteInPlace 3rdparty/stout/include/stout/posix/os.hpp \
+      --subst-var-by tar ${tarWithGzip}/bin/tar
 
     substituteInPlace src/cli/mesos-scp \
       --subst-var-by scp ${openssh}/bin/scp
 
+    substituteInPlace src/common/command_utils.cpp \
+      --subst-var-by curl      ${curl}/bin/curl \
+      --subst-var-by gzip      ${gzip}/bin/gzip \
+      --subst-var-by sha512sum ${coreutils}/bin/sha512sum \
+      --subst-var-by tar       ${tarWithGzip}/bin/tar
+
     substituteInPlace src/launcher/fetcher.cpp \
+      --subst-var-by cp    ${coreutils}/bin/cp \
       --subst-var-by gzip  ${gzip}/bin/gzip \
-      --subst-var-by tar   ${gnutar}/bin/tar \
+      --subst-var-by tar   ${tarWithGzip}/bin/tar \
       --subst-var-by unzip ${unzip}/bin/unzip
 
     substituteInPlace src/python/cli/src/mesos/cli.py \
       --subst-var-by mesos-resolve $out/bin/mesos-resolve
 
+    substituteInPlace src/python/native_common/ext_modules.py.in \
+      --replace "-lprotobuf" \
+                "${pythonProtobuf.protobuf.lib}/lib/libprotobuf.a"
+
+    substituteInPlace src/slave/containerizer/mesos/isolators/gpu/volume.cpp \
+      --subst-var-by cp    ${coreutils}/bin/cp \
+      --subst-var-by which ${which}/bin/which
+
     substituteInPlace src/slave/containerizer/mesos/isolators/posix/disk.cpp \
-      --subst-var-by du ${coreutils}/bin/du \
-      --subst-var-by cp ${coreutils}/bin/cp
+      --subst-var-by du ${coreutils}/bin/du
 
     substituteInPlace src/slave/containerizer/mesos/provisioner/backends/copy.cpp \
-      --subst-var-by cp ${coreutils}/bin/cp
+      --subst-var-by cp ${coreutils}/bin/cp \
+      --subst-var-by rm ${coreutils}/bin/rm
 
     substituteInPlace src/uri/fetchers/copy.cpp \
       --subst-var-by cp ${coreutils}/bin/cp
@@ -83,23 +113,48 @@ in stdenv.mkDerivation rec {
     substituteInPlace src/uri/fetchers/docker.cpp \
       --subst-var-by curl ${curl}/bin/curl
 
+    substituteInPlace src/Makefile.am \
+      --subst-var-by mavenRepo ${mavenRepo} \
+      --replace "-lprotobuf" \
+                "${pythonProtobuf.protobuf.lib}/lib/libprotobuf.a"
+
   '' + lib.optionalString stdenv.isLinux ''
 
     substituteInPlace src/linux/perf.cpp \
       --subst-var-by perf ${perf}/bin/perf
 
+    substituteInPlace src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp \
+      --subst-var-by mount ${utillinux}/bin/mount
+
+    substituteInPlace src/slave/containerizer/mesos/isolators/filesystem/linux.cpp \
+      --subst-var-by mount ${utillinux}/bin/mount
+
     substituteInPlace src/slave/containerizer/mesos/isolators/filesystem/shared.cpp \
       --subst-var-by mount ${utillinux}/bin/mount
 
+    substituteInPlace src/slave/containerizer/mesos/isolators/gpu/isolator.cpp \
+      --subst-var-by mount ${utillinux}/bin/mount
+
     substituteInPlace src/slave/containerizer/mesos/isolators/namespaces/pid.cpp \
       --subst-var-by mount ${utillinux}/bin/mount
 
+    substituteInPlace src/slave/containerizer/mesos/isolators/network/cni/cni.cpp \
+      --subst-var-by mount ${utillinux}/bin/mount
+
+    substituteInPlace src/slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp \
+      --subst-var-by iptables ${iptables}/bin/iptables
+
     substituteInPlace src/slave/containerizer/mesos/isolators/network/port_mapping.cpp \
-      --subst-var-by tc      ${iproute}/bin/tc \
+      --subst-var-by ethtool ${ethtool}/sbin/ethtool \
       --subst-var-by ip      ${iproute}/bin/ip \
       --subst-var-by mount   ${utillinux}/bin/mount \
-      --subst-var-by sh      ${stdenv.shell} \
-      --subst-var-by ethtool ${ethtool}/sbin/ethtool
+      --subst-var-by tc      ${iproute}/bin/tc
+
+    substituteInPlace src/slave/containerizer/mesos/isolators/volume/image.cpp \
+      --subst-var-by mount   ${utillinux}/bin/mount
+
+    substituteInPlace src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp \
+      --subst-var-by mount   ${utillinux}/bin/mount
   '';
 
   configureFlags = [
@@ -108,7 +163,6 @@ in stdenv.mkDerivation rec {
     "--with-svn=${subversion.dev}"
     "--with-leveldb=${leveldb}"
     "--with-glog=${glog}"
-    "--with-glog=${glog}"
     "--enable-optimize"
     "--disable-python-dependency-install"
     "--enable-ssl"
diff --git a/pkgs/applications/networking/cluster/mesos/maven_repo.patch b/pkgs/applications/networking/cluster/mesos/maven_repo.patch
deleted file mode 100644
index 9ee12976fde..00000000000
--- a/pkgs/applications/networking/cluster/mesos/maven_repo.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/src/Makefile.am b/src/Makefile.am
-index ae2740a..1df91a7 100644
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -1310,7 +1310,7 @@ if HAS_JAVA
- 
- $(MESOS_JAR): $(MESOS_JAR_SOURCE) $(MESOS_JAR_GENERATED) java/mesos.pom
- 	@echo "Building mesos-$(PACKAGE_VERSION).jar ..."
--	@cd $(abs_top_builddir)/src/java && $(MVN) -f mesos.pom clean package
-+	@cd $(abs_top_builddir)/src/java && $(MVN) -f mesos.pom -Dmaven.repo.local=@mavenRepo@ clean package
- 
- # Convenience library for JNI bindings.
- # TODO(Charles Reiss): We really should be building the Java library
diff --git a/pkgs/applications/networking/cluster/mesos/nixos.patch b/pkgs/applications/networking/cluster/mesos/nixos.patch
index 032357e452d..78e374b8d6b 100644
--- a/pkgs/applications/networking/cluster/mesos/nixos.patch
+++ b/pkgs/applications/networking/cluster/mesos/nixos.patch
@@ -1,5 +1,18 @@
+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<Nothing> 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 a29967d..290b98b 100644
+index a29967dcb..290b98b50 100644
 --- a/3rdparty/stout/include/stout/os/posix/fork.hpp
 +++ b/3rdparty/stout/include/stout/os/posix/fork.hpp
 @@ -369,7 +369,7 @@ private:
@@ -11,48 +24,97 @@ index a29967d..290b98b 100644
        EXIT(EXIT_FAILURE)
          << "Failed to execute '" << command << "': " << os::strerror(errno);
      } else if (wait.isSome()) {
-diff --git a/3rdparty/stout/include/stout/os/posix/shell.hpp b/3rdparty/stout/include/stout/os/posix/shell.hpp
-index 1d73ae5..9bf89b5 100644
---- a/3rdparty/stout/include/stout/os/posix/shell.hpp
-+++ b/3rdparty/stout/include/stout/os/posix/shell.hpp
-@@ -37,7 +37,7 @@ namespace Shell {
- // received by the callee, usually the command name and `arg1` is the
- // second command argument received by the callee.
- 
--constexpr const char* name = "sh";
-+constexpr const char* name = "@sh@";
- constexpr const char* arg0 = "sh";
- constexpr const char* arg1 = "-c";
+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<std::string> getenv(const std::string& key)
+ inline Try<Nothing> tar(const std::string& path, const std::string& archive)
+ {
+   Try<std::string> tarOut =
+-    os::shell("tar %s %s %s", "-czf", archive.c_str(), path.c_str());
++    os::shell("@tar@ %s %s %s", "-czf", archive.c_str(), path.c_str());
  
+   if (tarOut.isError()) {
+     return Error("Failed to archive " + path + ": " + tarOut.error());
 diff --git a/src/Makefile.am b/src/Makefile.am
-index 28dd151..36fc6ec 100644
+index 3bcc0f2df..e5cbc57e8 100644
 --- a/src/Makefile.am
 +++ b/src/Makefile.am
-@@ -1528,7 +1528,8 @@ if HAS_JAVA
+@@ -1545,7 +1545,7 @@ if HAS_JAVA
  
  $(MESOS_JAR): $(MESOS_JAR_SOURCE) $(MESOS_JAR_GENERATED) java/mesos.pom
  	@echo "Building mesos-$(PACKAGE_VERSION).jar ..."
 -	@cd $(abs_top_builddir)/src/java && $(MVN) -B -f mesos.pom clean package
 +	@cd $(abs_top_builddir)/src/java && $(MVN) -B -f mesos.pom -Dmaven.repo.local=@mavenRepo@ clean package
-+
  
  # 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 a71ab07..feed8c4 100755
+index a71ab0708..1043d1b3c 100755
 --- a/src/cli/mesos-scp
 +++ b/src/cli/mesos-scp
-@@ -19,7 +19,7 @@ if sys.version_info < (2,6,0):
+@@ -19,7 +19,8 @@ if sys.version_info < (2,6,0):
  
  
  def scp(host, src, dst):
 -    cmd = 'scp -pr %s %s' % (src, host + ':' + dst)
 +    cmd = '@scp@ -pr %s %s' % (src, host + ':' + dst)
++
      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<Nothing> tar(
+ 
+   argv.emplace_back(input);
+ 
+-  return launch("tar", argv)
++  return launch("@tar@", argv)
+     .then([]() { return Nothing(); });
+ }
+ 
+@@ -162,7 +162,7 @@ Future<Nothing> untar(
+     argv.emplace_back(directory.get());
+   }
+ 
+-  return launch("tar", argv)
++  return launch("@tar@", argv)
+     .then([]() { return Nothing(); });
+ }
+ 
+@@ -170,7 +170,7 @@ Future<Nothing> untar(
+ Future<string> sha512(const Path& input)
+ {
+ #ifdef __linux__
+-  const string cmd = "sha512sum";
++  const string cmd = "@sha512sum@";
+   vector<string> argv = {
+     cmd,
+     input             // Input file to compute shasum.
+@@ -206,7 +206,7 @@ Future<Nothing> gzip(const Path& input)
+     input
+   };
+ 
+-  return launch("gzip", argv)
++  return launch("@gzip@", argv)
+     .then([]() { return Nothing(); });
+ }
+ 
+@@ -219,7 +219,7 @@ Future<Nothing> decompress(const Path& input)
+     input
+   };
+ 
+-  return launch("gzip", argv)
++  return launch("@gzip@", argv)
+     .then([]() { return Nothing(); });
+ }
+ 
 diff --git a/src/launcher/fetcher.cpp b/src/launcher/fetcher.cpp
-index 4456c28..e22c8fc 100644
+index 4456c2813..e22c8fc03 100644
 --- a/src/launcher/fetcher.cpp
 +++ b/src/launcher/fetcher.cpp
 @@ -68,13 +68,13 @@ static Try<bool> extract(
@@ -82,11 +144,11 @@ index 4456c28..e22c8fc 100644
    LOG(INFO) << "Copying resource with command:" << command;
  
 diff --git a/src/linux/perf.cpp b/src/linux/perf.cpp
-index ea823b3..170f54d 100644
+index aa31982eb..8b5331b17 100644
 --- a/src/linux/perf.cpp
 +++ b/src/linux/perf.cpp
-@@ -125,7 +125,7 @@ private:
-     // NOTE: The watchdog process places perf in its own process group
+@@ -127,7 +127,7 @@ private:
+     // NOTE: The supervisor childhook places perf in its own process group
      // and will kill the perf process when the parent dies.
      Try<Subprocess> _perf = subprocess(
 -        "perf",
@@ -104,37 +166,51 @@ index ea823b3..170f54d 100644
      command << " --event " << event;
    }
 diff --git a/src/linux/systemd.cpp b/src/linux/systemd.cpp
-index 619aa27..c1cbfe4 100644
+index 6318f48fc..394d88d47 100644
 --- a/src/linux/systemd.cpp
 +++ b/src/linux/systemd.cpp
-@@ -196,12 +196,19 @@ bool exists()
+@@ -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 {
      // (1) Test whether `/sbin/init` links to systemd.
 -    const Result<string> realpath = os::realpath("/sbin/init");
 -    if (realpath.isError() || realpath.isNone()) {
 -      LOG(WARNING) << "Failed to test /sbin/init for systemd environment: "
--                   << realpath.error();
+-                   << (realpath.isError() ? realpath.error()
+-                                          : "does not exist");
 -
 -      return false;
-+    // cstrahan: first assume we're on NixOS, then try non-NixOS
++    // cstrahan(nixos): first assume we're on NixOS, then try non-NixOS
 +    Result<string> realpath = os::realpath("/run/current-system/systemd/lib/systemd/systemd");
 +    Result<string> realpathNixOS = realpath;
 +    if (realpathNixOS.isError() || realpathNixOS.isNone()) {
 +      Result<string> realpathNonNixOS = realpath = os::realpath("/sbin/init");
 +      if (realpathNonNixOS.isError() || realpathNonNixOS.isNone()) {
 +        LOG(WARNING) << "Failed to test /run/current-system/systemd/lib/systemd/systemd for systemd environment: "
-+                     << realpathNixOS.error();
++                     << (realpathNixOS.isError() ? realpathNixOS.error()
++                                                 : "does not exist");
 +        LOG(WARNING) << "Failed to test /sbin/init for systemd environment: "
-+                     << realpathNonNixOS.error();
++                     << (realpathNonNixOS.isError() ? realpathNonNixOS.error()
++                                                    : "does not exist");
 +
 +        return false;
 +      }
      }
  
      CHECK_SOME(realpath);
+@@ -278,6 +286,10 @@ Path hierarchy()
+ 
+ Try<Nothing> daemonReload()
+ {
++  // cstrahan(nixos): should we patch these `systemctl`s?
++  // probably don't want to hard-code a particular systemd store path here,
++  // but if we use /run/current-system/sw/bin/systemctl,
++  // we won't be able to support non-NixOS distros.
+   Try<string> 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 f342992..354abf4 100644
+index f342992e0..354abf443 100644
 --- a/src/python/cli/src/mesos/cli.py
 +++ b/src/python/cli/src/mesos/cli.py
 @@ -40,7 +40,7 @@ def resolve(master):
@@ -146,11 +222,70 @@ index f342992..354abf4 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
+@@ -499,7 +499,7 @@ Future<Option<ContainerLaunchInfo>> DockerVolumeIsolatorProcess::_prepare(
+     // unsafe arbitrary commands).
+     CommandInfo* command = launchInfo.add_pre_exec_commands();
+     command->set_shell(false);
+-    command->set_value("mount");
++    command->set_value("@mount@");
+     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<Isolator*> LinuxFilesystemIsolatorProcess::create(const Flags& flags)
+       // here because 'create' will only be invoked during
+       // initialization.
+       Try<string> mount = os::shell(
+-          "mount --bind %s %s && "
+-          "mount --make-private %s && "
+-          "mount --make-shared %s",
++          "@mount@ --bind %s %s && "
++          "@mount@ --make-private %s && "
++          "@mount@ --make-shared %s",
+           workDir->c_str(),
+           workDir->c_str(),
+           workDir->c_str(),
+@@ -180,8 +180,8 @@ Try<Isolator*> LinuxFilesystemIsolatorProcess::create(const Flags& flags)
+       LOG(INFO) << "Making '" << workDir.get() << "' a shared mount";
+ 
+       Try<string> mount = os::shell(
+-          "mount --make-private %s && "
+-          "mount --make-shared %s",
++          "@mount@ --make-private %s && "
++          "@mount@ --make-shared %s",
+           workDir->c_str(),
+           workDir->c_str());
+ 
+@@ -404,7 +404,7 @@ Try<vector<CommandInfo>> LinuxFilesystemIsolatorProcess::getPreExecCommands(
+ 
+     CommandInfo command;
+     command.set_shell(false);
+-    command.set_value("mount");
++    command.set_value("@mount@");
+     command.add_arguments("mount");
+     command.add_arguments("-n");
+     command.add_arguments("--rbind");
+@@ -569,7 +569,7 @@ Try<vector<CommandInfo>> LinuxFilesystemIsolatorProcess::getPreExecCommands(
+     // TODO(jieyu): Consider the mode in the volume.
+     CommandInfo command;
+     command.set_shell(false);
+-    command.set_value("mount");
++    command.set_value("@mount@");
+     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 51d1518..783adb5 100644
+index a1283e5ee..a918427bf 100644
 --- a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
 +++ b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
-@@ -204,7 +204,7 @@ Future<Option<ContainerLaunchInfo>> SharedFilesystemIsolatorProcess::prepare(
+@@ -207,7 +207,7 @@ Future<Option<ContainerLaunchInfo>> SharedFilesystemIsolatorProcess::prepare(
      }
  
      launchInfo.add_pre_exec_commands()->set_value(
@@ -159,36 +294,148 @@ index 51d1518..783adb5 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<Option<ContainerLaunchInfo>> NvidiaGpuIsolatorProcess::_prepare(
+     }
+ 
+     launchInfo.add_pre_exec_commands()->set_value(
+-      "mount --no-mtab --rbind --read-only " +
++      "@mount@ --no-mtab --rbind --read-only " +
+       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> NvidiaVolume::create()
+     string path = path::join(hostPath, "bin", binary);
+ 
+     if (!os::exists(path)) {
+-      string command = "which " + binary;
++      string command = "@which@ " + binary;
+       Try<string> which = os::shell(command);
+ 
+       if (which.isSome()) {
+@@ -295,7 +295,7 @@ Try<NvidiaVolume> NvidiaVolume::create()
+                               : "No such file or directory"));
+         }
+ 
+-        command = "cp " + realpath.get() + " " + path;
++        command = "@cp@ " + realpath.get() + " " + path;
+         Try<string> cp = os::shell(command);
+         if (cp.isError()) {
+           return Error("Failed to os::shell '" + command + "': " + cp.error());
+@@ -367,7 +367,7 @@ Try<NvidiaVolume> NvidiaVolume::create()
+             Path(realpath.get()).basename());
+ 
+         if (!os::exists(libraryPath)) {
+-          string command = "cp " + realpath.get() + " " + libraryPath;
++          string command = "@cp@ " + realpath.get() + " " + libraryPath;
+           Try<string> 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 b41e266..e07c163 100644
+index 0d9ec57d9..a177e4476 100644
 --- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
 +++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
-@@ -163,7 +163,7 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
-   // containers cannot see the namespace bind mount of other
-   // containers.
-   launchInfo.add_pre_exec_commands()->set_value(
--      "mount -n --bind " + string(PID_NS_BIND_MOUNT_MASK_DIR) +
-+      "@mount@ -n --bind " + string(PID_NS_BIND_MOUNT_MASK_DIR) +
-       " " + string(PID_NS_BIND_MOUNT_ROOT));
- 
-   // Mount /proc for the container's pid namespace to show the
-@@ -176,9 +176,9 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
-   // -n flag so the mount is not added to the mtab where it will not
-   // be correctly removed with the namespace terminates.
-   launchInfo.add_pre_exec_commands()->set_value(
--      "mount none /proc --make-private -o rec");
-+      "@mount@ none /proc --make-private -o rec");
+@@ -94,7 +94,7 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
+   //
+   // TOOD(jieyu): Consider unmount the existing /proc.
    launchInfo.add_pre_exec_commands()->set_value(
 -      "mount -n -t proc proc /proc -o nosuid,noexec,nodev");
 +      "@mount@ -n -t proc proc /proc -o nosuid,noexec,nodev");
  
    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<Isolator*> NetworkCniIsolatorProcess::create(const Flags& flags)
+       // here because 'create' will only be invoked during
+       // initialization.
+       Try<string> mount = os::shell(
+-          "mount --bind %s %s && "
+-          "mount --make-private %s && "
+-          "mount --make-shared %s",
++          "@mount@ --bind %s %s && "
++          "@mount@ --make-private %s && "
++          "@mount@ --make-shared %s",
+           rootDir->c_str(),
+           rootDir->c_str(),
+           rootDir->c_str(),
+@@ -284,8 +284,8 @@ Try<Isolator*> NetworkCniIsolatorProcess::create(const Flags& flags)
+       LOG(INFO) << "Making '" << rootDir.get() << "' a shared mount";
+ 
+       Try<string> mount = os::shell(
+-          "mount --make-private %s && "
+-          "mount --make-shared %s",
++          "@mount@ --make-private %s && "
++          "@mount@ --make-shared %s",
+           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<Nothing> 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.
+-      iptables -w -t nat --list %s
++      @iptables@ -w -t nat --list %s
+       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<Nothing> 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.
+-        (iptables -w -t nat -N %s || exit 1)
++        (@iptables@ -w -t nat -N %s || exit 1)
+ 
+         # Once the chain has been installed add a rule in the PREROUTING
+         # chain to jump to this chain for any packets that are
+         # destined to a local address.
+-        (iptables -w -t nat -A PREROUTING \
++        (@iptables@ -w -t nat -A PREROUTING \
+         -m addrtype --dst-type LOCAL -j %s || exit 1)
+ 
+         # For locally generated packets we need a rule in the OUTPUT
+         # chain as well, since locally generated packets directly hit
+         # the output CHAIN, bypassing PREROUTING.
+-        (iptables -w -t nat -A OUTPUT \
++        (@iptables@ -w -t nat -A OUTPUT \
+         ! -d 127.0.0.0/8 -m addrtype \
+         --dst-type LOCAL -j %s || exit 1)
+       fi
+ 
+       # Within the `chain` go ahead and install the DNAT rule, if it
+       # does not exist.
+-      (iptables -w -t nat -C %s || iptables -t nat -A %s))~",
++      (@iptables@ -w -t nat -C %s || @iptables@ -t nat -A %s))~",
+       chain,
+       chain,
+       chain,
+@@ -362,7 +362,7 @@ Try<Nothing> PortMapper::delPortMapping()
+       # The iptables command searches for the DNAT rules with tag
+       # "container_id: <CNI_CONTAINERID>", and if it exists goes ahead
+       # and deletes it.
+-      iptables -w -t nat -S %s | sed "/%s/ s/-A/iptables -w -t nat -D/e")~",
++      @iptables@ -w -t nat -S %s | sed "/%s/ s/-A/@iptables@ -w -t nat -D/e")~",
+       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 79ee960..d55a353 100644
+index 20fb6ab35..46c160977 100644
 --- a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
 +++ b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
-@@ -1392,19 +1392,19 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const Flags& flags)
+@@ -1393,19 +1393,19 @@ Try<Isolator*> 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.
@@ -211,7 +458,7 @@ index 79ee960..d55a353 100644
    if (checkCommandIp.isError()) {
      return Error("Check command 'ip' failed: " + checkCommandIp.error());
    }
-@@ -1924,9 +1924,9 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const Flags& flags)
+@@ -1925,9 +1925,9 @@ Try<Isolator*> 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<string> mount = os::shell(
@@ -224,7 +471,7 @@ index 79ee960..d55a353 100644
          bindMountRoot->c_str(),
          bindMountRoot->c_str(),
          bindMountRoot->c_str(),
-@@ -1943,8 +1943,8 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const Flags& flags)
+@@ -1944,8 +1944,8 @@ Try<Isolator*> 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<string> mount = os::shell(
@@ -235,7 +482,7 @@ index 79ee960..d55a353 100644
            bindMountRoot->c_str(),
            bindMountRoot->c_str());
  
-@@ -1963,8 +1963,8 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const Flags& flags)
+@@ -1964,8 +1964,8 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const Flags& flags)
            // so that they are in different peer groups.
            if (entry.shared() == bindMountEntry->shared()) {
              Try<string> mount = os::shell(
@@ -246,14 +493,16 @@ index 79ee960..d55a353 100644
                  bindMountRoot->c_str(),
                  bindMountRoot->c_str());
  
-@@ -3916,13 +3916,13 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -3911,6 +3911,8 @@ Try<Nothing> 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.
++// cstrahan(nixos): this is executed in the container,
++// so we don't want to substitute paths here.
+ string PortMappingIsolatorProcess::scripts(Info* info)
  {
    ostringstream script;
- 
--  script << "#!/bin/sh\n";
-+  script << "#!@sh@\n";
-   script << "set -xe\n";
- 
+@@ -3921,7 +3923,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.
@@ -262,7 +511,7 @@ index 79ee960..d55a353 100644
  
    // Disable IPv6 when IPv6 module is loaded as IPv6 packets won't be
    // forwarded anyway.
-@@ -3930,7 +3930,7 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -3929,7 +3931,7 @@ string PortMappingIsolatorProcess::scripts(Info* info)
           << " echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6\n";
  
    // Configure lo and eth0.
@@ -271,7 +520,7 @@ index 79ee960..d55a353 100644
           << " mtu " << hostEth0MTU << " up\n";
  
    // NOTE: This is mostly a kernel issue: in veth_xmit() the kernel
-@@ -3939,12 +3939,12 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -3938,12 +3940,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.
@@ -288,7 +537,7 @@ index 79ee960..d55a353 100644
  
    // Restrict the ephemeral ports that can be used by the container.
    script << "echo " << info->ephemeralPorts.lower() << " "
-@@ -3973,19 +3973,19 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -3972,19 +3974,19 @@ string PortMappingIsolatorProcess::scripts(Info* info)
    }
  
    // Set up filters on lo and eth0.
@@ -312,7 +561,7 @@ index 79ee960..d55a353 100644
           << " protocol ip"
           << " prio " << Priority(IP_FILTER_PRIORITY, NORMAL).get() << " u32"
           << " flowid ffff:0"
-@@ -3996,7 +3996,7 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -3995,7 +3997,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.
@@ -321,7 +570,7 @@ index 79ee960..d55a353 100644
             << " protocol ip"
             << " prio " << Priority(IP_FILTER_PRIORITY, HIGH).get() << " u32"
             << " flowid ffff:0"
-@@ -4005,7 +4005,7 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -4004,7 +4006,7 @@ string PortMappingIsolatorProcess::scripts(Info* info)
  
      // Traffic going to host loopback IP and ports assigned to this
      // container will be redirected to lo.
@@ -330,7 +579,7 @@ index 79ee960..d55a353 100644
             << " protocol ip"
             << " prio " << Priority(IP_FILTER_PRIORITY, NORMAL).get() << " u32"
             << " flowid ffff:0"
-@@ -4017,14 +4017,14 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -4016,14 +4018,14 @@ string PortMappingIsolatorProcess::scripts(Info* info)
    }
  
    // Do not forward the ICMP packet if the destination IP is self.
@@ -347,7 +596,7 @@ index 79ee960..d55a353 100644
           << " protocol ip"
           << " prio " << Priority(ICMP_FILTER_PRIORITY, NORMAL).get() << " u32"
           << " flowid ffff:0"
-@@ -4033,9 +4033,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -4032,9 +4034,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
           << net::IPNetwork::LOOPBACK_V4().address() << "\n";
  
    // Display the filters created on eth0 and lo.
@@ -359,7 +608,7 @@ index 79ee960..d55a353 100644
           << " parent " << ingress::HANDLE << "\n";
  
    // If throughput limit for container egress traffic exists, use HTB
-@@ -4047,9 +4047,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -4046,9 +4048,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
    // throughput. TBF requires other parameters such as 'burst' that
    // HTB already has default values for.
    if (egressRateLimitPerContainer.isSome()) {
@@ -371,12 +620,12 @@ index 79ee960..d55a353 100644
             << CONTAINER_TX_HTB_HANDLE << " classid "
             << CONTAINER_TX_HTB_CLASS_ID << " htb rate "
             << egressRateLimitPerContainer.get().bytes() * 8 << "bit\n";
-@@ -4060,12 +4060,12 @@ string PortMappingIsolatorProcess::scripts(Info* info)
+@@ -4059,12 +4061,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.
 -    script << "tc qdisc add dev " << eth0
-+    script << "@tC@ qdisc add dev " << eth0
++    script << "@tc@ qdisc add dev " << eth0
             << " parent " << CONTAINER_TX_HTB_CLASS_ID << " fq_codel\n";
  
      // Display the htb qdisc and class created on eth0.
@@ -388,11 +637,11 @@ index 79ee960..d55a353 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 3dfe7ad..4288666 100644
+index db0583386..542586370 100644
 --- a/src/slave/containerizer/mesos/isolators/posix/disk.cpp
 +++ b/src/slave/containerizer/mesos/isolators/posix/disk.cpp
-@@ -492,7 +492,7 @@ private:
-     // NOTE: The monitor watchdog will watch the parent process and kill
+@@ -540,7 +540,7 @@ private:
+     // NOTE: The supervisor childhook will watch the parent process and kill
      // the 'du' process in case that the parent die.
      Try<Subprocess> s = subprocess(
 -        "du",
@@ -400,11 +649,37 @@ index 3dfe7ad..4288666 100644
          command,
          Subprocess::PATH("/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<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::_prepare(
+ 
+     CommandInfo* command = launchInfo.add_pre_exec_commands();
+     command->set_shell(false);
+-    command->set_value("mount");
++    command->set_value("@mount@");
+     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<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
+ 
+       CommandInfo* command = launchInfo.add_pre_exec_commands();
+       command->set_shell(false);
+-      command->set_value("mount");
++      command->set_value("@mount@");
+       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 b9f6d7a..0fcf455 100644
+index 9c5354e5f..a73a9692e 100644
 --- a/src/slave/containerizer/mesos/provisioner/backends/copy.cpp
 +++ b/src/slave/containerizer/mesos/provisioner/backends/copy.cpp
-@@ -141,7 +141,7 @@ Future<Nothing> CopyBackendProcess::_provision(
+@@ -147,7 +147,7 @@ Future<Nothing> CopyBackendProcess::_provision(
  #endif // __APPLE__ || __FreeBSD__
  
    Try<Subprocess> s = subprocess(
@@ -413,11 +688,20 @@ index b9f6d7a..0fcf455 100644
        args,
        Subprocess::PATH("/dev/null"),
        Subprocess::PATH("/dev/null"),
+@@ -180,7 +180,7 @@ Future<bool> CopyBackendProcess::destroy(const string& rootfs)
+   vector<string> argv{"rm", "-rf", rootfs};
+ 
+   Try<Subprocess> s = subprocess(
+-      "rm",
++      "@rm@",
+       argv,
+       Subprocess::PATH("/dev/null"),
+       Subprocess::FD(STDOUT_FILENO),
 diff --git a/src/uri/fetchers/copy.cpp b/src/uri/fetchers/copy.cpp
-index f095ad6..ee0c2a7 100644
+index 2cfef5ab0..8a62f7699 100644
 --- a/src/uri/fetchers/copy.cpp
 +++ b/src/uri/fetchers/copy.cpp
-@@ -88,7 +88,7 @@ Future<Nothing> CopyFetcherPlugin::fetch(
+@@ -97,7 +97,7 @@ Future<Nothing> CopyFetcherPlugin::fetch(
    const vector<string> argv = {"cp", "-a", uri.path(), directory};
  
    Try<Subprocess> s = subprocess(
@@ -427,10 +711,10 @@ index f095ad6..ee0c2a7 100644
        Subprocess::PATH("/dev/null"),
        Subprocess::PIPE(),
 diff --git a/src/uri/fetchers/curl.cpp b/src/uri/fetchers/curl.cpp
-index cc3f9ee..691d2d9 100644
+index 7b746d619..12bbb04df 100644
 --- a/src/uri/fetchers/curl.cpp
 +++ b/src/uri/fetchers/curl.cpp
-@@ -98,7 +98,7 @@ Future<Nothing> CurlFetcherPlugin::fetch(
+@@ -107,7 +107,7 @@ Future<Nothing> CurlFetcherPlugin::fetch(
    };
  
    Try<Subprocess> s = subprocess(
@@ -440,10 +724,10 @@ index cc3f9ee..691d2d9 100644
        Subprocess::PATH("/dev/null"),
        Subprocess::PIPE(),
 diff --git a/src/uri/fetchers/docker.cpp b/src/uri/fetchers/docker.cpp
-index 211be6f..d7e3771 100644
+index 3f38dddfb..fd991ee74 100644
 --- a/src/uri/fetchers/docker.cpp
 +++ b/src/uri/fetchers/docker.cpp
-@@ -113,7 +113,7 @@ static Future<http::Response> curl(
+@@ -114,7 +114,7 @@ static Future<http::Response> curl(
  
    // TODO(jieyu): Kill the process if discard is called.
    Try<Subprocess> s = subprocess(
@@ -452,7 +736,7 @@ index 211be6f..d7e3771 100644
        argv,
        Subprocess::PATH("/dev/null"),
        Subprocess::PIPE(),
-@@ -212,7 +212,7 @@ static Future<int> download(
+@@ -213,7 +213,7 @@ static Future<int> download(
  
    // TODO(jieyu): Kill the process if discard is called.
    Try<Subprocess> s = subprocess(
diff --git a/pkgs/applications/networking/cluster/mesos/rb36610.patch b/pkgs/applications/networking/cluster/mesos/rb36610.patch
index c3b1b290422..bee578cc3e9 100644
--- a/pkgs/applications/networking/cluster/mesos/rb36610.patch
+++ b/pkgs/applications/networking/cluster/mesos/rb36610.patch
@@ -1,11 +1,12 @@
 diff --git a/src/linux/fs.cpp b/src/linux/fs.cpp
-index ea0891e320154b85a21ed2d138c192821efae9cd..7b24c377c9a28cad91738305c273fb53a4dc7365 100644
+index 913e233..c2917a6 100644
 --- a/src/linux/fs.cpp
 +++ b/src/linux/fs.cpp
-@@ -19,6 +19,7 @@
+@@ -17,6 +17,7 @@
  #include <errno.h>
  #include <stdio.h>
  #include <string.h>
 +#include <syscall.h>
-
+ 
  #include <linux/limits.h>
+ #include <linux/unistd.h>
diff --git a/pkgs/applications/networking/cluster/mesos/rb51324.patch b/pkgs/applications/networking/cluster/mesos/rb51324.patch
deleted file mode 100644
index 68ef866161f..00000000000
--- a/pkgs/applications/networking/cluster/mesos/rb51324.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-diff --git a/3rdparty/stout/include/stout/os/ls.hpp b/3rdparty/stout/include/stout/os/ls.hpp
-index f8da9ef..6d549d3 100644
---- a/3rdparty/stout/include/stout/os/ls.hpp
-+++ b/3rdparty/stout/include/stout/os/ls.hpp
-@@ -18,6 +18,7 @@
- #else
- #include <dirent.h>
- #endif // __WINDOWS__
-+
- #include <stdlib.h>
- 
- #include <list>
-@@ -26,8 +27,6 @@
- #include <stout/error.hpp>
- #include <stout/try.hpp>
- 
--#include <stout/os/direntsize.hpp>
--
- 
- namespace os {
- 
-@@ -36,36 +35,32 @@ inline Try<std::list<std::string>> ls(const std::string& directory)
-   DIR* dir = opendir(directory.c_str());
- 
-   if (dir == nullptr) {
--    // Preserve `opendir` error.
-     return ErrnoError("Failed to opendir '" + directory + "'");
-   }
- 
--  dirent* temp = (dirent*) malloc(os::dirent_size(dir));
--
--  if (temp == nullptr) {
--    // Preserve `malloc` error.
--    ErrnoError error("Failed to allocate directory entries");
--    closedir(dir);
--    return error;
--  }
--
-   std::list<std::string> result;
-   struct dirent* entry;
--  int error;
- 
--  while ((error = readdir_r(dir, temp, &entry)) == 0 && entry != nullptr) {
-+  // Zero `errno` before starting to call `readdir`. This is necessary
-+  // to allow us to determine when `readdir` returns an error.
-+  errno = 0;
-+
-+  while ((entry = readdir(dir)) != NULL) {
-     if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
-       continue;
-     }
-     result.push_back(entry->d_name);
-   }
- 
--  free(temp);
--  closedir(dir);
-+  if (errno != 0) {
-+    // Preserve `readdir` error.
-+    Error error = ErrnoError("Failed to read directory");
-+    closedir(dir);
-+    return error;
-+  }
- 
--  if (error != 0) {
--    // Preserve `readdir_r` error.
--    return ErrnoError("Failed to read directories");
-+  if (closedir(dir) == -1) {
-+    return ErrnoError("Failed to close directory");
-   }
- 
-   return result;
diff --git a/pkgs/applications/networking/cluster/mesos/rb51325.patch b/pkgs/applications/networking/cluster/mesos/rb51325.patch
deleted file mode 100644
index 5c5ce00730b..00000000000
--- a/pkgs/applications/networking/cluster/mesos/rb51325.patch
+++ /dev/null
@@ -1,157 +0,0 @@
-diff --git a/3rdparty/stout/include/Makefile.am b/3rdparty/stout/include/Makefile.am
-index 1f2ee85..b0b08d8 100644
---- a/3rdparty/stout/include/Makefile.am
-+++ b/3rdparty/stout/include/Makefile.am
-@@ -64,7 +64,6 @@ nobase_include_HEADERS =			\
-   stout/os/chroot.hpp				\
-   stout/os/close.hpp				\
-   stout/os/constants.hpp			\
--  stout/os/direntsize.hpp			\
-   stout/os/environment.hpp			\
-   stout/os/exists.hpp				\
-   stout/os/fcntl.hpp				\
-@@ -108,7 +107,6 @@ nobase_include_HEADERS =			\
-   stout/os/posix/chown.hpp			\
-   stout/os/posix/chroot.hpp			\
-   stout/os/posix/close.hpp			\
--  stout/os/posix/direntsize.hpp			\
-   stout/os/posix/exists.hpp			\
-   stout/os/posix/fcntl.hpp			\
-   stout/os/posix/fork.hpp			\
-@@ -134,7 +132,6 @@ nobase_include_HEADERS =			\
-   stout/os/windows/bootid.hpp			\
-   stout/os/windows/chroot.hpp			\
-   stout/os/windows/close.hpp			\
--  stout/os/windows/direntsize.hpp		\
-   stout/os/windows/exists.hpp			\
-   stout/os/windows/fcntl.hpp			\
-   stout/os/windows/fork.hpp			\
-diff --git a/3rdparty/stout/include/stout/os/direntsize.hpp b/3rdparty/stout/include/stout/os/direntsize.hpp
-deleted file mode 100644
-index 819f99a..0000000
---- a/3rdparty/stout/include/stout/os/direntsize.hpp
-+++ /dev/null
-@@ -1,26 +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 __STOUT_OS_DIRENTSIZE_HPP__
--#define __STOUT_OS_DIRENTSIZE_HPP__
--
--
--// For readability, we minimize the number of #ifdef blocks in the code by
--// splitting platform specifc system calls into separate directories.
--#ifdef __WINDOWS__
--#include <stout/os/windows/direntsize.hpp>
--#else
--#include <stout/os/posix/direntsize.hpp>
--#endif // __WINDOWS__
--
--
--#endif // __STOUT_OS_DIRENTSIZE_HPP__
-diff --git a/3rdparty/stout/include/stout/os/posix/direntsize.hpp b/3rdparty/stout/include/stout/os/posix/direntsize.hpp
-deleted file mode 100644
-index 9d8f72e..0000000
---- a/3rdparty/stout/include/stout/os/posix/direntsize.hpp
-+++ /dev/null
-@@ -1,42 +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 __STOUT_OS_POSIX_DIRENTSIZE_HPP__
--#define __STOUT_OS_POSIX_DIRENTSIZE_HPP__
--
--#include <dirent.h>
--#include <unistd.h>
--
--
--namespace os {
--
--inline size_t dirent_size(DIR* dir)
--{
--  // Calculate the size for a "directory entry".
--  long name_max = fpathconf(dirfd(dir), _PC_NAME_MAX);
--
--  // If we don't get a valid size, check NAME_MAX, but fall back on
--  // 255 in the worst case ... Danger, Will Robinson!
--  if (name_max == -1) {
--    name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
--  }
--
--  size_t name_end = (size_t) offsetof(dirent, d_name) + name_max + 1;
--
--  size_t size = (name_end > sizeof(dirent) ? name_end : sizeof(dirent));
--
--  return size;
--}
--
--} // namespace os {
--
--#endif // __STOUT_OS_POSIX_DIRENTSIZE_HPP__
-diff --git a/3rdparty/stout/include/stout/os/windows/direntsize.hpp b/3rdparty/stout/include/stout/os/windows/direntsize.hpp
-deleted file mode 100644
-index 7c8c7a0..0000000
---- a/3rdparty/stout/include/stout/os/windows/direntsize.hpp
-+++ /dev/null
-@@ -1,43 +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 __STOUT_OS_WINDOWS_DIRENTSIZE_HPP__
--#define __STOUT_OS_WINDOWS_DIRENTSIZE_HPP__
--
--#include <stout/internal/windows/dirent.hpp>
--
--#include <stout/windows.hpp>
--
--
--namespace os {
--
--inline size_t dirent_size(DIR* dir)
--{
--  // NOTE: Size calculation logic here is much simpler than on POSIX because
--  // our implementation of `dirent` is constant-sized. In particular, on POSIX,
--  // we usually have to calculate the maximum name size for a path before we
--  // can alloc a correctly-size `dirent`, but on Windows, `dirent.d_name` is
--  // always `MAX_PATH` bytes in size.
--  //
--  // This follows closely from the Windows standard API data structures for
--  // manipulating and querying directories. For example, the structures
--  // `WIN32_FIND_DATA`[1] (which in many ways is the Windows equivalent of
--  // `dirent`) has a field `cFileName` (which is much like `d_name`) that is
--  // also `MAX_PATH` in size.
--  //
--  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx
--  return sizeof(dirent);
--}
--
--} // namespace os {
--
--#endif // __STOUT_OS_WINDOWS_DIRENTSIZE_HPP__
diff --git a/pkgs/development/interpreters/python/build-python-package-setuptools.nix b/pkgs/development/interpreters/python/build-python-package-setuptools.nix
index f077533ecfe..eab10372674 100644
--- a/pkgs/development/interpreters/python/build-python-package-setuptools.nix
+++ b/pkgs/development/interpreters/python/build-python-package-setuptools.nix
@@ -53,4 +53,4 @@ in attrs // {
     fi
     ${postShellHook}
   '';
-}
\ No newline at end of file
+}
diff --git a/pkgs/development/libraries/protobuf/generic.nix b/pkgs/development/libraries/protobuf/generic.nix
index 47f66c83ff5..2e962298550 100644
--- a/pkgs/development/libraries/protobuf/generic.nix
+++ b/pkgs/development/libraries/protobuf/generic.nix
@@ -1,4 +1,4 @@
-{ stdenv, version, src
+{ stdenv, lib, version, src
 , autoreconfHook, zlib, gtest
 , ...
 }:
@@ -21,6 +21,26 @@ stdenv.mkDerivation rec {
 
   buildInputs = [ autoreconfHook zlib ];
 
+  # The generated C++ code uses static initializers which mutate a global data
+  # structure. This causes problems for an executable when:
+  #
+  # 1) it dynamically links to two libs, both of which contain generated C++ for
+  #    the same proto file, and
+  # 2) the two aforementioned libs both dynamically link to libprotobuf.
+  #
+  # One solution is to statically link libprotobuf, that way the global
+  # variables are not shared; in fact, this is necessary for the python Mesos
+  # binding to not crash, as the python lib contains two C extensions which
+  # both refer to the same proto schema.
+  #
+  # See: https://github.com/NixOS/nixpkgs/pull/19064#issuecomment-255082684
+  #      https://github.com/google/protobuf/issues/1489
+  dontDisableStatic = true;
+  configureFlags = [
+    "CFLAGS=-fPIC"
+    "CXXFLAGS=-fPIC"
+  ];
+
   doCheck = true;
 
   meta = {
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index 7ca61ccbf4d..66af0cd36e7 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -19146,18 +19146,35 @@ in {
     '';
 
     preConfigure = optionalString (versionAtLeast protobuf.version "2.6.0") ''
-      PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
-      PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
+      export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+      export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
     '';
 
-    checkPhase = if versionAtLeast protobuf.version "2.6.0" then ''
+    preBuild = optionalString (versionAtLeast protobuf.version "2.6.0") ''
+      ${python}/bin/${python.executable} setup.py build_ext --cpp_implementation
+    '';
+
+    checkPhase = ''
+      runHook preCheck
+    '' + (if versionAtLeast protobuf.version "2.6.0" then ''
       ${python.executable} setup.py google_test --cpp_implementation
+      echo "sanity checking the C extension . . ."
+      echo "import google.protobuf.descriptor" | ${python.executable}
     '' else ''
       ${python.executable} setup.py test
+    '') + ''
+      runHook postCheck
     '';
 
     installFlags = optional (versionAtLeast protobuf.version "2.6.0") "--install-option='--cpp_implementation'";
 
+    # the _message.so isn't installed, so we'll do that manually.
+    # if someone can figure out a less hacky way to get the _message.so to
+    # install, please do replace this.
+    postInstall = optionalString (versionAtLeast protobuf.version "2.6.0") ''
+      cp -v $(find build -name "_message*") $out/${python.sitePackages}/google/protobuf/pyext
+    '';
+
     doCheck = true;
 
     meta = {