From: Tarek Mahmoud Sayed Date: Thu, 10 Mar 2022 20:36:32 +0000 (-0800) Subject: [release/6.0] Backport Fix PerformanceCounter's when running with Globalization Invar... X-Git-Tag: accepted/tizen/unified/20221103.165808~169^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d4ba2cccbecc0f4d7466dbbd5d443231e4441282;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [release/6.0] Backport Fix PerformanceCounter's when running with Globalization Invariant Mode (#65537) * [dotnet/runtime] Backport Fix PerformanceCounter's when running with Globalization Invariant Mode (PR #65414) * Add GeneratePackageOnBuild & ServicingVersion project properties --- diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 5d99e22..8de7e12 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -4,6 +4,8 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);netcoreapp3.1-windows;netcoreapp3.1;netstandard2.0;net461 $(NoWarn);CA1847 true + true + 1 Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters. Commonly Used Types: diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs index bdd47b9..567a8bf 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs @@ -45,12 +45,12 @@ namespace System.Diagnostics private const string LanguageKeyword = "language"; private const string DllName = "netfxperf.dll"; - private const int EnglishLCID = 0x009; - private static volatile string s_computerName; private static volatile string s_iniFilePath; private static volatile string s_symbolFilePath; + private static CultureInfo s_englishCulture; + private PerformanceMonitor _performanceMonitor; private readonly string _machineName; private readonly string _perfLcid; @@ -79,6 +79,25 @@ namespace System.Diagnostics } } + private static CultureInfo EnglishCulture + { + get + { + if (s_englishCulture is null) + { + try + { + s_englishCulture = CultureInfo.GetCultureInfo("en"); + } + catch + { + s_englishCulture = CultureInfo.InvariantCulture; + } + } + return s_englishCulture; + } + } + internal PerformanceCounterLib(string machineName, string lcid) { _machineName = machineName; @@ -277,11 +296,11 @@ namespace System.Diagnostics internal static bool CategoryExists(string machine, string category) { - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); if (library.CategoryExists(category)) return true; - if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -349,11 +368,11 @@ namespace System.Diagnostics internal static bool CounterExists(string machine, string category, string counter) { - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); bool categoryExists = false; bool counterExists = library.CounterExists(category, counter, ref categoryExists); - if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (!categoryExists && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -753,7 +772,7 @@ namespace System.Diagnostics culture = culture.Parent; } - library = GetPerformanceCounterLib(machineName, new CultureInfo(EnglishLCID)); + library = GetPerformanceCounterLib(machineName, EnglishCulture); return library.GetCategories(); } @@ -772,7 +791,7 @@ namespace System.Diagnostics //First check the current culture for the category. This will allow //PerformanceCounterCategory.CategoryHelp to return localized strings. - if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; @@ -788,7 +807,7 @@ namespace System.Diagnostics //We did not find the category walking up the culture hierarchy. Try looking // for the category in the default culture English. - library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + library = GetPerformanceCounterLib(machine, EnglishCulture); help = library.GetCategoryHelp(category); if (help == null) @@ -808,9 +827,9 @@ namespace System.Diagnostics internal static CategorySample GetCategorySample(string machine, string category) { - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); CategorySample sample = library.GetCategorySample(category); - if (sample == null && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (sample == null && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -845,11 +864,11 @@ namespace System.Diagnostics internal static string[] GetCounters(string machine, string category) { - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); bool categoryExists = false; string[] counters = library.GetCounters(category, ref categoryExists); - if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (!categoryExists && CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -910,7 +929,7 @@ namespace System.Diagnostics //First check the current culture for the counter. This will allow //PerformanceCounter.CounterHelp to return localized strings. - if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -925,7 +944,7 @@ namespace System.Diagnostics //We did not find the counter walking up the culture hierarchy. Try looking // for the counter in the default culture English. - library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + library = GetPerformanceCounterLib(machine, EnglishCulture); help = library.GetCounterHelp(category, counter, ref categoryExists); if (!categoryExists) @@ -990,7 +1009,8 @@ namespace System.Diagnostics internal static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture) { - string lcidString = culture.LCID.ToString("X3", CultureInfo.InvariantCulture); + // EnglishCulture.LCID == 9 will be false only if running with Globalization Invariant Mode. Use "009" at that time as default English language identifier. + string lcidString = EnglishCulture.LCID == 9 ? culture.LCID.ToString("X3", CultureInfo.InvariantCulture) : "009"; machineName = (machineName == "." ? ComputerName : machineName).ToLowerInvariant(); @@ -1135,11 +1155,11 @@ namespace System.Diagnostics internal static bool IsCustomCategory(string machine, string category) { - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); if (library.IsCustomCategory(category)) return true; - if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) @@ -1174,10 +1194,10 @@ namespace System.Diagnostics { PerformanceCounterCategoryType categoryType = PerformanceCounterCategoryType.Unknown; - PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); + PerformanceCounterLib library = GetPerformanceCounterLib(machine, EnglishCulture); if (!library.FindCustomCategory(category, out categoryType)) { - if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) + if (CultureInfo.CurrentCulture.Parent.Name != EnglishCulture.Name) { CultureInfo culture = CultureInfo.CurrentCulture; while (culture != CultureInfo.InvariantCulture) diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs index bfaf5fb..c8df93e 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Globalization; using System.Collections; using System.Collections.Specialized; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Diagnostics.Tests @@ -287,6 +289,32 @@ namespace System.Diagnostics.Tests } } + private static bool CanRunInInvariantMode => RemoteExecutor.IsSupported && !PlatformDetection.IsNetFramework; + + [ConditionalTheory(nameof(CanRunInInvariantMode))] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData(true)] + [InlineData(false)] + public static void RunWithGlobalizationInvariantModeTest(bool predefinedCultures) + { + ProcessStartInfo psi = new ProcessStartInfo() { UseShellExecute = false }; + psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1"); + psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", predefinedCultures ? "1" : "0"); + RemoteExecutor.Invoke(() => + { + // Ensure we are running inside the Globalization invariant mode. + Assert.Equal("", CultureInfo.CurrentCulture.Name); + + // This test ensure creating PerformanceCounter object while we are running with Globalization Invariant Mode. + // PerformanceCounter used to create cultures using LCID's which fail in Globalization Invariant Mode. + // This test ensure no failure should be encountered in this case. + using (PerformanceCounter counterSample = new PerformanceCounter("Processor", "Interrupts/sec", "0", ".")) + { + Assert.Equal("Processor", counterSample.CategoryName); + } + }, new RemoteInvokeOptions { StartInfo = psi}).Dispose(); + } + public static PerformanceCounter CreateCounterWithCategory(string name, bool readOnly, PerformanceCounterCategoryType categoryType ) { var category = Helpers.CreateCategory(name, categoryType);