diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs index f0b6774ac45503..01cf81f01ef424 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs @@ -61,6 +61,6 @@ public static void ApplyUpdate(Assembly assembly, ReadOnlySpan metadataDel /// Returns true if the apply assembly update is enabled and available. /// [FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")] - public static bool IsSupported { get; } = IsApplyUpdateSupported(); + public static bool IsSupported { get; } = !IsHotReloadDisabled && IsApplyUpdateSupported(); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs index fa929ccba5d438..563f2e27f7fc50 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs @@ -5,7 +5,7 @@ namespace System.Reflection.Metadata { - public static class MetadataUpdater + public static partial class MetadataUpdater { public static void ApplyUpdate(Assembly assembly, ReadOnlySpan metadataDelta, ReadOnlySpan ilDelta, ReadOnlySpan pdbDelta) { diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2c5f234cc2d163..16f43f682dfe8d 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -793,6 +793,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs new file mode 100644 index 00000000000000..585350ee3fc23a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Reflection.Metadata +{ + public static partial class MetadataUpdater + { + /// + /// Returns true if hot reload is explicitly disabled via the DOTNET_HOTRELOAD_DISABLED environment variable + /// or the System.Reflection.Metadata.HotReloadDisabled AppContext switch set to true. + /// + internal static bool IsHotReloadDisabled => + AppContextConfigHelper.GetBooleanConfig("System.Reflection.Metadata.HotReloadDisabled", "DOTNET_HOTRELOAD_DISABLED"); + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index c8576441586296..ab5388b7c5149d 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Reflection.Metadata @@ -1157,5 +1158,20 @@ void TestIncreaseMetadataRowSize() Assert.Equal("x800", pars[0].Name); }); } + + [ConditionalFact(typeof(ApplyUpdateUtil), nameof(ApplyUpdateUtil.IsRemoteExecutorSupported))] + void TestHotReloadDisabledEnvironmentVariable() + { + // Check that DOTNET_HOTRELOAD_DISABLED=1 disables MetadataUpdater.IsSupported. + var options = new RemoteInvokeOptions(); + options.StartInfo.EnvironmentVariables.Add( + ApplyUpdateUtil.DotNetModifiableAssembliesSwitch, ApplyUpdateUtil.DotNetModifiableAssembliesValue); + options.StartInfo.EnvironmentVariables.Add("DOTNET_HOTRELOAD_DISABLED", "1"); + + RemoteExecutor.Invoke(static () => + { + Assert.False(MetadataUpdater.IsSupported); + }, options).Dispose(); + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs index 67306e03081e28..749e1d474f2de7 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs @@ -7,7 +7,7 @@ namespace System.Reflection.Metadata { - public static class MetadataUpdater + public static partial class MetadataUpdater { /// /// Updates the specified assembly using the provided metadata, IL and PDB deltas. @@ -51,7 +51,7 @@ public static void ApplyUpdate(Assembly assembly, ReadOnlySpan metadataDel internal static string GetCapabilities() => s_ApplyUpdateCapabilities.Value; [FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")] - public static bool IsSupported { get; } = ApplyUpdateEnabled(justComponentCheck: 0) != 0; + public static bool IsSupported { get; } = !IsHotReloadDisabled && ApplyUpdateEnabled(justComponentCheck: 0) != 0; private static readonly Lazy s_ApplyUpdateCapabilities = new Lazy(InitializeApplyUpdateCapabilities);