From b60c91cdb9de36d2356ee8f135de65473f282209 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Tue, 14 Nov 2017 17:45:08 -0800 Subject: [PATCH] Enable Globalization Invariant mode using Environment Variable (#15024) * Enable Globalization Invariant mode using Environment Variable * Prefix the environment variable name with DOTNET_ * Address the feedback --- src/mscorlib/src/System/CLRConfig.cs | 10 +++++----- .../System/Globalization/GlobalizationMode.Unix.cs | 4 ++-- .../Globalization/GlobalizationMode.Windows.cs | 2 +- .../src/System/Globalization/GlobalizationMode.cs | 21 ++++++++++++++++++++- src/vm/clrconfignative.cpp | 10 ++++++++-- src/vm/clrconfignative.h | 2 +- 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/mscorlib/src/System/CLRConfig.cs b/src/mscorlib/src/System/CLRConfig.cs index d97922f..4c208cd 100644 --- a/src/mscorlib/src/System/CLRConfig.cs +++ b/src/mscorlib/src/System/CLRConfig.cs @@ -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 diff --git a/src/mscorlib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/mscorlib/src/System/Globalization/GlobalizationMode.Unix.cs index 6896029..a9f7e87 100644 --- a/src/mscorlib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/mscorlib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -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); } diff --git a/src/mscorlib/src/System/Globalization/GlobalizationMode.Windows.cs b/src/mscorlib/src/System/Globalization/GlobalizationMode.Windows.cs index 1be79f3..2738d5b 100644 --- a/src/mscorlib/src/System/Globalization/GlobalizationMode.Windows.cs +++ b/src/mscorlib/src/System/Globalization/GlobalizationMode.Windows.cs @@ -8,7 +8,7 @@ namespace System.Globalization { private static bool GetGlobalizationInvariantMode() { - return CLRConfig.GetBoolValue(c_InvariantModeConfigSwitch); + return GetInvariantSwitchValue(); } } } diff --git a/src/mscorlib/src/System/Globalization/GlobalizationMode.cs b/src/mscorlib/src/System/Globalization/GlobalizationMode.cs index 8f83098..a9d30eb 100644 --- a/src/mscorlib/src/System/Globalization/GlobalizationMode.cs +++ b/src/mscorlib/src/System/Globalization/GlobalizationMode.cs @@ -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; + } } } diff --git a/src/vm/clrconfignative.cpp b/src/vm/clrconfignative.cpp index 11b9eb5..8b09537 100644 --- a/src/vm/clrconfignative.cpp +++ b/src/vm/clrconfignative.cpp @@ -9,13 +9,19 @@ #include "clrconfignative.h" #include -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); } diff --git a/src/vm/clrconfignative.h b/src/vm/clrconfignative.h index a60d119..8673699 100644 --- a/src/vm/clrconfignative.h +++ b/src/vm/clrconfignative.h @@ -8,7 +8,7 @@ class ClrConfigNative { public: - static BOOL QCALLTYPE GetConfigBoolValue(LPCWSTR name); + static BOOL QCALLTYPE GetConfigBoolValue(LPCWSTR name, BOOL *exist); }; #endif // _CLRCONFIGNATIVE_H_ -- 2.7.4