You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2016/08/27 01:20:03 UTC

[4/6] mesos git commit: Windows: Corrected subprocess environment variables.

Windows: Corrected subprocess environment variables.

Windows processes have a minimum set of environment variables required
to load prerequisites, such as shared libraries.  These environment
variables are generally found in the system's environment.

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


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

Branch: refs/heads/master
Commit: 9d3786353b4a4c357f9196d9659bac4582dd0176
Parents: ec30c1f
Author: Daniel Pravat <dp...@outlook.com>
Authored: Fri Aug 26 17:23:22 2016 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Fri Aug 26 18:19:03 2016 -0700

----------------------------------------------------------------------
 .../include/process/windows/subprocess.hpp      | 70 +++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9d378635/3rdparty/libprocess/include/process/windows/subprocess.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/windows/subprocess.hpp b/3rdparty/libprocess/include/process/windows/subprocess.hpp
index 6bb54c8..f452f67 100644
--- a/3rdparty/libprocess/include/process/windows/subprocess.hpp
+++ b/3rdparty/libprocess/include/process/windows/subprocess.hpp
@@ -30,6 +30,8 @@
 #include <stout/os/close.hpp>
 #include <stout/os/environment.hpp>
 
+#include <userEnv.h>
+
 using std::map;
 using std::string;
 using std::vector;
@@ -62,6 +64,56 @@ inline void close(
   }
 }
 
+// Retrieves system environment in a `std::map`, ignoring
+// the current process's environment variables.
+inline Option<map<string, string>> getSystemEnvironment()
+{
+  std::wstring_convert<std::codecvt<wchar_t, char, mbstate_t>,
+    wchar_t> converter;
+
+  map<string, string> systemEnvironment;
+  wchar_t* environmentEntry = nullptr;
+
+  // Get the system environment.
+  // The third parameter (bool) tells the function *not* to inherit
+  // variables from the current process.
+  if (!CreateEnvironmentBlock((LPVOID*)&environmentEntry, nullptr, FALSE)) {
+    return None();
+  }
+
+  // Save the environment block in order to destroy it later.
+  wchar_t* environmentBlock = environmentEntry;
+
+  while (*environmentEntry != L'\0') {
+    // Each environment block contains the environment variables as follows:
+    // Var1=Value1\0
+    // Var2=Value2\0
+    // Var3=Value3\0
+    // ...
+    // VarN=ValueN\0\0
+    // The name of an environment variable cannot include an equal sign (=).
+
+    wchar_t * separator = wcschr(environmentEntry, L'=');
+    std::wstring varName = std::wstring(environmentEntry, separator);
+    std::wstring varVal = std::wstring(separator + 1);
+
+    // Mesos variables are upper case. Convert system variables to
+    // match the name provided by the scheduler in case of a collision.
+    std::transform(varName.begin(), varName.end(), varName.begin(), ::towupper);
+
+    // The system environment has priority. Force `ANSI` usage until the code
+    // is converted to UNICODE.
+    systemEnvironment.insert_or_assign(
+      converter.to_bytes(varName.c_str()),
+      converter.to_bytes(varVal.c_str()));
+
+    environmentEntry += varName.length() + varVal.length() + 2;
+  }
+
+  DestroyEnvironmentBlock(environmentBlock);
+
+  return systemEnvironment;
+}
 
 // Creates a null-terminated array of null-terminated strings that will be
 // passed to `CreateProcess` as the `lpEnvironment` argument, as described by
@@ -70,6 +122,10 @@ inline void close(
 // environments, so it should not be used in conjunction with the
 // `CREATE_UNICODE_ENVIRONMENT` flag.
 //
+// NOTE: This function will add the system's environment variables into
+// the returned string. These variables take precedence over the provided
+// `env` and are generally necessary in order to launch things on Windows.
+//
 // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
 inline Option<string> createProcessEnvironment(
     const Option<map<string, string>>& env)
@@ -78,8 +134,20 @@ inline Option<string> createProcessEnvironment(
     return None();
   }
 
+  Option<map<string, string>> systemEnvironment = getSystemEnvironment();
+
+  // The system environment must be non-empty.
+  // No subprocesses will be able to launch if the system environment is blank.
+  CHECK(systemEnvironment.isSome() && systemEnvironment.get().size() > 0);
+
+  map<string, string> combinedEnvironment = env.get();
+
+  foreachpair(const string& key, const string& value, systemEnvironment.get()) {
+    combinedEnvironment[key] = value;
+  }
+
   string environmentString;
-  foreachpair (const string& key, const string& value, env.get()) {
+  foreachpair (const string& key, const string& value, combinedEnvironment) {
     environmentString += key + '=' + value + '\0';
   }