Repository navigation
Consider a hot reload feature switch for linking #51159
Description
Background and Motivation
We are going to have a variety of places across the core libraries that use MetadataUpdateHandlerAttribute to react to hot reload updates. Some of these handlers will have zero impact unless used (other than their presence in the library binaries) while others will have additional code on "normal" execution code paths, e.g. to track things that later need to be cleared. We should look at either using an existing feature switch (e.g. Debugging.IsSupported) or a new feature switch (e.g. AssemblyExtensions.IsApplyUpdateAvailable) that we tie all of these to and use to both link away and disable any expense when not required. We should aim to use the same switch across the whole stack (currently ASP.NET is using its own property).
Proposed API
namespace System.Reflection.Metadata
{
public static class AssemblyExtensions
{
/// <summary>
/// Returns true if the apply assembly update is enabled and available.
/// </summary>
public static bool IsApplyUpdateAvailable { get; }
}
}The .NET Core runtime will basically implement like this (and will cache the value in a static):
IsApplyUpdateAvailable => Debugger.IsAttached || Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES") != "" || Environment.GetEnvironmentVariable("COMPlus_ForceEnc") == "1";The feature switch support in the runtime build files include this property so the conditional apply update code is elided on release builds.
Usage Examples
if (AssemblyExtensions.IsApplyUpdateAvailable)
{
// Hot reload/ENC specific initialization or bookkeeping code
}The hot reload agent can use this to ensure that it can actually apply updates to the application. Third party libraries can use it to run some apply update specific initialization or bookkeeping code.
Risks
Low. This API is used only in very limited cases and by very few developers (mostly internal).
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
pranavkm commentedon Apr 13, 2021
If I understand this correctly, would we be teaching the trimmer to remove all code paths inside a
HotReload.IsSupportedswitch?SamMonoRT commentedon Apr 13, 2021
@lambdageek fyi
eerhardt commentedon Apr 13, 2021
If we added this switch, the trimmer would only remove code paths inside the
HotReload.IsSupportedswitch when the switch was set tofalse.There are other scenarios where the trimmer runs, but you still want to debug and hot-reload your app. One that comes to mind is Xamarin apps - See https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/OneDotNet.md#dotnet-build--publish.
marek-safar commentedon Apr 14, 2021
Is the logic fully detached from Debugging.IsSupported feature switch? In other words would settings like Debugging.IsSupported = false, HotReload.IsSupported = true work?
7 remaining items
terrajobst commentedon Jun 22, 2021
AssemblyExtensions.ApplyUpdate()IsSupportedmikem8361 commentedon Jun 22, 2021
We would need to add one more related API: GetApplyUpdateCapabilities() and probably rename it to GetCapabilities(). It is currently internal so the tests and hot reload agent/Roslyn use reflection but maybe we should make it public.
stephentoub commentedon Jun 23, 2021
Yup, we discussed that, it was just left out of the summary. We landed on GetCapabilities(). We didn't discuss changing it to be public.
We also talked about how we may want to stage this by first adding the new class and changing the existing one to just delegate to it but not yet remove it, wait until the rest of the components have been updated to use the new type, and only then delete the old one (but hopefully that cycle can happen relatively quickly, as we'd want to delete the old one soon-ish).