Enable Globalization Invariant mode using Environment Variable (#15024)
authorTarek Mahmoud Sayed <tarekms@microsoft.com>
Wed, 15 Nov 2017 01:45:08 +0000 (17:45 -0800)
committerGitHub <noreply@github.com>
Wed, 15 Nov 2017 01:45:08 +0000 (17:45 -0800)
* Enable Globalization Invariant mode using Environment Variable

* Prefix the environment variable name with DOTNET_

* Address the feedback

src/mscorlib/src/System/CLRConfig.cs
src/mscorlib/src/System/Globalization/GlobalizationMode.Unix.cs
src/mscorlib/src/System/Globalization/GlobalizationMode.Windows.cs
src/mscorlib/src/System/Globalization/GlobalizationMode.cs
src/vm/clrconfignative.cpp
src/vm/clrconfignative.h

index d97922f..4c208cd 100644 (file)
@@ -9,20 +9,20 @@ using System.Security;
 
 namespace System
 {
-    // CLRConfig is mainly reading the config switch values. this is used when we cannot use the AppContext class 
-    // one example, is using the context switch in the globalization code which require to read the switch very 
+    // CLRConfig is mainly reading the config switch values. this is used when we cannot use the AppContext class
+    // one example, is using the context switch in the globalization code which require to read the switch very
     // early even before the appdomain get initialized.
     // In general AppContext should be used instead of CLRConfig if there is no reason prevent that.
     internal class CLRConfig
     {
-        internal static bool GetBoolValue(string switchName)
+        internal static bool GetBoolValue(string switchName, out bool exist)
         {
-            return GetConfigBoolValue(switchName);
+            return GetConfigBoolValue(switchName, out exist);
         }
 
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
         [SuppressUnmanagedCodeSecurity]
-        private extern static bool GetConfigBoolValue(string configSwitchName);
+        private extern static bool GetConfigBoolValue(string configSwitchName, out bool exist);
     }
 }  // namespace System
 
index 6896029..a9f7e87 100644 (file)
@@ -8,12 +8,12 @@ namespace System.Globalization
     {
         private static bool GetGlobalizationInvariantMode()
         {
-            bool invariantEnabled = CLRConfig.GetBoolValue(c_InvariantModeConfigSwitch);
+            bool invariantEnabled = GetInvariantSwitchValue();
             if (!invariantEnabled)
             {
                 if (Interop.GlobalizationInterop.LoadICU() == 0)
                 {
-                    string message = "Couldn't find a valid ICU package installed on the system. " + 
+                    string message = "Couldn't find a valid ICU package installed on the system. " +
                                     "Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support.";
                     Environment.FailFast(message);
                 }
index 1be79f3..2738d5b 100644 (file)
@@ -8,7 +8,7 @@ namespace System.Globalization
     {
         private static bool GetGlobalizationInvariantMode()
         {
-            return CLRConfig.GetBoolValue(c_InvariantModeConfigSwitch);
+            return GetInvariantSwitchValue();
         }
     }
 }
index 8f83098..a9d30eb 100644 (file)
@@ -6,7 +6,26 @@ namespace System.Globalization
 {
     internal sealed partial class GlobalizationMode
     {
-        private const string c_InvariantModeConfigSwitch = "System.Globalization.Invariant";
         internal static bool Invariant { get; } = GetGlobalizationInvariantMode();
+
+        // GetInvariantSwitchValue calls CLRConfig first to detect if the switch is defined in the config file.
+        // if the switch is defined we just use the value of this switch. otherwise, we'll try to get the switch
+        // value from the environment variable if it is defined.
+        internal static bool GetInvariantSwitchValue()
+        {
+            bool exist;
+            bool ret = CLRConfig.GetBoolValue("System.Globalization.Invariant", out exist);
+            if (!exist)
+            {
+                // Linux doesn't support environment variable names include dots
+                string switchValue = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
+                if (switchValue != null)
+                {
+                    ret = switchValue.Equals("true", StringComparison.OrdinalIgnoreCase) || switchValue.Equals("1");
+                }
+            }
+
+            return ret;
+        }
     }
 }
index 11b9eb5..8b09537 100644 (file)
@@ -9,13 +9,19 @@
 #include "clrconfignative.h"
 #include <configuration.h>
 
-BOOL QCALLTYPE ClrConfigNative::GetConfigBoolValue(LPCWSTR name)
+BOOL QCALLTYPE ClrConfigNative::GetConfigBoolValue(LPCWSTR name, BOOL *exist)
 {
     QCALL_CONTRACT;
 
     BOOL retValue = FALSE;
+    *exist = FALSE;
     BEGIN_QCALL;
-    retValue = Configuration::GetKnobBooleanValue(name, FALSE);
+
+    if (Configuration::GetKnobStringValue(name) != nullptr)
+    {
+        *exist = TRUE;
+        retValue = Configuration::GetKnobBooleanValue(name, FALSE);
+    }
     END_QCALL;
     return(retValue);
 }
index a60d119..8673699 100644 (file)
@@ -8,7 +8,7 @@
 class ClrConfigNative
 {
 public:
-    static BOOL QCALLTYPE GetConfigBoolValue(LPCWSTR name);
+    static BOOL QCALLTYPE GetConfigBoolValue(LPCWSTR name, BOOL *exist);
 };
 
 #endif // _CLRCONFIGNATIVE_H_