Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use AssemblyLoadContext Name instead of AppDomain #9353

Merged

Conversation

bording
Copy link
Contributor

@bording bording commented Oct 21, 2023

Fixes #9348

Context

When MSBuild was updated to isolate tasks into a custom AssemblyLoadContext, AssemblyLoadsTracker was not updated to be aware of this change. This means that the log messages always say AppDomain: [Default] and don't show any information about which AssemblyLoadContext was used to load the assembly.

Changes Made

When FEATURE_ASSEMBLYLOADCONTEXT is defined:

  • AssemblyLoadsTracker now populates AssemblyLoadBuildEventArgs with the name of the AssemblyLoadContext used to load the assembly . The appDomainDescriptor parameter is re-used to do this.
  • A new string resource has been added to update the text of AssemblyLoadBuildEventArgs.Message to use label the AppDomainDescriptor value as "AssemblyLoadContext" instead of "AppDomain".

Testing

I couldn't find any existing tests that covered AssemblyLoadsTracker behavior, so I haven't updated or added any tests yet. Unit tests added.

Notes

AssemblyLoadContext.GetLoadContext can return null, but only if the assembly loaded isn't derived from RuntimeAssembly. The only way I'm aware that would be true is if MetadataLoadContext was used to load the assembly as ReflectionOnly, and I wouldn't think that would be a relevant case here. For now, if it was null for some reason, I've made appDomainDescriptor have the value "unknown". Otherwise, if I let the null through, AssemblyLoadBuildEventArgs would print "[Default]" in its message, which would not be correct.

I added a new string resource in a separate commit because I wasn't sure if that would be okay or not. I know that means there's some translation work to do. Looking at the existing translations for TaskAssemblyLoaded, since "AppDomain" isn't translated, it looks like it should just be a matter of copying the existing one and replacing that one word.

@bording bording force-pushed the assembly-loads-use-assemblyloadcontext branch from f875fa1 to d8cb65f Compare October 21, 2023 04:37
@bording bording force-pushed the assembly-loads-use-assemblyloadcontext branch from d8cb65f to 6256d67 Compare October 21, 2023 19:30
@bording bording force-pushed the assembly-loads-use-assemblyloadcontext branch from 6256d67 to 95f0f64 Compare October 21, 2023 19:37
@bording bording marked this pull request as ready for review October 21, 2023 21:59
@JanKrivanek
Copy link
Member

Testing

I couldn't find any existing tests that covered AssemblyLoadsTracker behavior, so I haven't updated or added any tests yet.

Could you possibly reuse/repurpose this integration test for assembly loads tracking?: https://github.com/dotnet/msbuild/blob/main/src/Build.UnitTests/BinaryLogger_Tests.cs#L192-L250 (plus if needed we have DotNetOnlyFact\Theory and WindowsFullFrameworkOnlyFact\Theory attributes to annotate tests running only on particular platform)

I added a new string resource in a separate commit because I wasn't sure if that would be okay or not. I know that means there's some translation work to do. Looking at the existing translations for TaskAssemblyLoaded, since "AppDomain" isn't translated, it looks like it should just be a matter of copying the existing one and replacing that one word.

All good.
Translations happens via separate automations in delayed automated PRs and it should be able to reuse (though in this case it probably won't as the strings differ - but that's no harm at all).

Copy link
Member

@JanKrivanek JanKrivanek left a comment

Choose a reason for hiding this comment

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

Thank you for this contribution!

It looks good to me as is.

Please try if you can have a simple test verifying the NET behavior.
Once this is cleared (or once we know reasons why it's complicated - so I can jump in to help) I'm happy to sign off

src/Framework/AssemblyLoadBuildEventArgs.cs Outdated Show resolved Hide resolved
@bording
Copy link
Contributor Author

bording commented Oct 23, 2023

Could you possibly reuse/repurpose this integration test for assembly loads tracking?: https://github.com/dotnet/msbuild/blob/main/src/Build.UnitTests/BinaryLogger_Tests.cs#L192-L250 (plus if needed we have DotNetOnlyFact\Theory and WindowsFullFrameworkOnlyFact\Theory attributes to annotate tests running only on particular platform)

I did see that test, so I'll take a look at extending it out a bit to cover the relevant part of the log change.

@bording
Copy link
Contributor Author

bording commented Oct 23, 2023

@JanKrivanek I took the test and split it into two versions, one that looks for the presence of AppDomain: [Default] being in the text, and the other looking for AssemblyLoadContext: Default.

Do you think it would be worth having a test that actually shows a task loading into a non-default AssemblyLoadContext? If so, can you point me to an example test of how to actually get a task assembly loaded in a test?

@JanKrivanek
Copy link
Member

JanKrivanek commented Oct 24, 2023

@JanKrivanek I took the test and split it into two versions, one that looks for the presence of AppDomain: [Default] being in the text, and the other looking for AssemblyLoadContext: Default.

Do you think it would be worth having a test that actually shows a task loading into a non-default AssemblyLoadContext? If so, can you point me to an example test of how to actually get a task assembly loaded in a test?

I leave up on you :-)

If you'd have to test another load context you'd need to have a task in separate assembly - all our tests use tasks that are compiled within the already loaded test assemblies, so you'd either need to add a separate project (too heavyweight for the test) or build one-off temp assembly within the test.
Then you can have test test the custom load context - similar to:

Assembly loaded during TaskRun: another-lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (location: <path>\another-lib.dll, MVID: 19ab2034-81ba-45df-b164-1ba0cb66da6b, AssemblyLoadContext: MSBuild plugin <path>\another-lib.dll)
Using "SimpleTask1" task from assembly "<path>\another-lib.dll".

If you'll leave the test as is (totally fine for the purpose they're validating) - those 2 differ only in that single assertion string - it'd be more readable if those 2 call a single helper giving it the assertion string as param.

[WindowsFullFrameworkOnlyFact]
Test1()
{
  TestImpl("Assertion text a");
}

[DotNetOnlyFact]
Test2()
{
  TestImpl("Assertion text b");
}

@rainersigwald
Copy link
Member

all our tests use tasks that are compiled within the already loaded test assemblies

Not all of them! One is actually perfect for this; check out https://github.com/dotnet/msbuild/blob/08494c73128451a3f7cfb47a5e9cbd63f5507a1f/src/Shared/UnitTests/TypeLoader_Dependencies_Tests.cs

@bording bording force-pushed the assembly-loads-use-assemblyloadcontext branch from 19f5cb9 to 5821a90 Compare October 25, 2023 00:31
@bording
Copy link
Contributor Author

bording commented Oct 25, 2023

@JanKrivanek I pushed up a new commit that adjusts the first test in the way you suggested, and I augmented the test @rainersigwald pointed out as well. How does that look?

Copy link
Member

@rainersigwald rainersigwald left a comment

Choose a reason for hiding this comment

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

Awesome, thanks!

src/Framework/AssemblyLoadBuildEventArgs.cs Outdated Show resolved Hide resolved
Copy link
Member

@JanKrivanek JanKrivanek left a comment

Choose a reason for hiding this comment

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

Thank you!

@rainersigwald rainersigwald enabled auto-merge (squash) October 25, 2023 16:38
@rainersigwald rainersigwald merged commit 4a626bc into dotnet:main Oct 26, 2023
8 checks passed
@bording bording deleted the assembly-loads-use-assemblyloadcontext branch October 26, 2023 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Assembly load events in .NET report AppDomain which isn't very helpful
3 participants