Skip to content

Conversation

@barosiak
Copy link
Member

Adds a config switch that unconditionally disables metadata updater.

Fixes #78540

@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jan 29, 2026
@barosiak barosiak added enhancement Product code improvement that does NOT require public API changes/additions area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jan 29, 2026
@steveisok steveisok requested a review from a team January 29, 2026 01:39
Copilot AI review requested due to automatic review settings January 30, 2026 21:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a configuration switch to fully disable hot-reload by introducing a new "none" value for the DOTNET_MODIFIABLE_ASSEMBLIES environment variable. This addresses issue #78540 where hot-reload couldn't be disabled when it was causing bugs, particularly when a debugger was attached.

Changes:

  • Introduced a tri-state enum (UNSET, NONE, DEBUG) to distinguish between "not configured", "explicitly disabled", and "explicitly enabled"
  • Updated both Mono and CoreCLR implementations to recognize the "none" value
  • Added test coverage for the new disable functionality

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/mono/mono/metadata/metadata-update.h Updated enum to add UNSET/NONE/DEBUG states with new numbering
src/mono/mono/component/hot_reload.c Added "none" value handling and updated logic (contains critical bug)
src/mono/mono/component/hot_reload-stub.c Updated stub to use UNSET instead of NONE for uninitialized state
src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs Minor whitespace fix
src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs Added constant for disabled value
src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs Added test for disable functionality
src/coreclr/vm/eeconfig.h Updated enum definition and method signatures for new tri-state
src/coreclr/vm/eeconfig.cpp Added parsing logic for "none" value
src/coreclr/vm/ceeload.cpp Updated condition to use new enum
src/coreclr/vm/assemblynative.cpp Updated logic to check for explicit disable

@jkotas
Copy link
Member

jkotas commented Jan 30, 2026

Could you please check that this env variable can be used to fully disable hot reload under VS? (#78218 (comment) is the motivating feedback.)

@jkotas
Copy link
Member

jkotas commented Jan 30, 2026

cc @tmat

Copilot AI review requested due to automatic review settings February 2, 2026 20:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@steveisok
Copy link
Member

Are you thinking Devs will be more confused than that, or that this scenario would happen often enough that we'd try to get explicit VS support for it? We've gone over 3 years since the bug to add the switch was filed suggesting these issues aren't very common.

I don't think there's a high bar. It probably would have been clearer if I had said I don't think what @barosiak posted in VS was a big deal. It would require someone in VS to make changes.

@barosiak
Copy link
Member Author

barosiak commented Feb 4, 2026

I think launchSettings.json would be the recommend place to apply this workaround. Can this be fixed?

It works, I was setting it incorrectly.

To sum up, there are two main ways to disable hot-reload when debugging in VS.

Using UI:

  1. Right click on the project in the solution explorer, open Properties
  2. Scroll down to the section Debug and click on Open debug launch profiles UI
  3. Add DOTNET_MODIFIABLE_ASSEMBLIES environment variable set to none
  4. Uncheck Enable Hot Reload

It should look like this:
image

Using launchSettings.json file:

  1. Create a file Properties\launchSettings.json (relative to your project folder) with contents shown below, or add "hotReloadEnabled": false and "DOTNET_MODIFIABLE_ASSEMBLIES": "none" to an existing file.
{
  "profiles": {
    "ConsoleApp": {
      "commandName": "Project",
      "hotReloadEnabled": false,
      "environmentVariables": {
        "DOTNET_MODIFIABLE_ASSEMBLIES": "none"
      }
    }
  }
}

@barosiak barosiak marked this pull request as ready for review February 4, 2026 21:30
@barosiak barosiak requested a review from thaystg as a code owner February 4, 2026 21:30
Copilot AI review requested due to automatic review settings February 4, 2026 21:30
@barosiak barosiak marked this pull request as draft February 4, 2026 21:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/mono/mono/component/hot_reload.c:361

  • The documentation comment should be updated to reflect the new "none" value. It currently states "all other values are ignored and metadata updates are disabled" but "none" is now a recognized value that explicitly disables metadata updates. Consider updating to: ""debug" means debuggable assemblies are modifiable, "none" explicitly disables metadata updates, and all other values are ignored and metadata updates are disabled."
hot_reload_update_enabled (int *modifiable_assemblies_out)
{
	static gboolean inited = FALSE;
	static int modifiable = MONO_MODIFIABLE_ASSM_UNSET;

	gboolean result = FALSE;
	if (!inited) {
		modifiable = hot_reload_update_enabled_slow_check (NULL);
		inited = TRUE;
		result = (modifiable == MONO_MODIFIABLE_ASSM_DEBUG);
		if (result) {
			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Metadata update enabled for debuggable assemblies");
		}
	}
	if (modifiable_assemblies_out)
		*modifiable_assemblies_out = modifiable;
	return result;
}

Copilot AI review requested due to automatic review settings February 10, 2026 00:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Copilot AI review requested due to automatic review settings February 10, 2026 01:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/mono/mono/component/hot_reload.c:360

  • hot_reload_update_enabled returns result, but result is only computed on the first call (inside if (!inited)). After initialization, subsequent calls will always return FALSE even if modifiable is MONO_MODIFIABLE_ASSM_DEBUG, which can incorrectly disable hot-reload behavior (e.g., callers like mono_metadata_update_enabled/inlining checks). Compute the return value from the cached modifiable on every call (or cache a separate static boolean).
hot_reload_update_enabled (int *modifiable_assemblies_out)
{
	static gboolean inited = FALSE;
	static int modifiable = MONO_MODIFIABLE_ASSM_UNSET;

	gboolean result = FALSE;
	if (!inited) {
		modifiable = hot_reload_update_enabled_slow_check (NULL);
		inited = TRUE;
		result = (modifiable == MONO_MODIFIABLE_ASSM_DEBUG);
		if (result) {
			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Metadata update enabled for debuggable assemblies");
		}
	}
	if (modifiable_assemblies_out)
		*modifiable_assemblies_out = modifiable;
	return result;

Copilot AI review requested due to automatic review settings February 12, 2026 23:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Diagnostics-coreclr enhancement Product code improvement that does NOT require public API changes/additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add config switch to fully disable hot-reload

5 participants