-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
DispatchProxy.Create reads AssemblyLoadContext.Name but treats it as an assembly name #80387
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
I think it's a .NET Runtime bug. DispatchProxyGenerator should not attempt to parse AssemblyLoadContext.Name as AssemblyName. Rather it should copy the string as is to AssemblyName.Name. AssemblyName.FullName is able to quote whatever you put in AssemblyName.Name. |
Can you work around by setting |
MSBuild generates an AssemblyLoadContext.Name that likely includes backslashes that AssemblyNameParser treats as escape characters: runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs Lines 384 to 410 in 97203d3
|
This use of AssemblyLoadContext.Name in DispatchProxy came from #62095, which has been locked, so I cannot comment there. It has not been fixed on the main branch of dotnet/runtime yet, and I did not find any dotnet/runtime issue filed for this problem. |
@KalleOlaviNiemitalo great analysis, thank you :) I've tried the Should I create a new issue in dotnet/runtime and close this one? |
I expect the team can move this issue to dotnet/runtime. For solutions that target .NET 6.0, I'd prefer global.json rather than the environment variable. One reason is that .NET SDK 7 will go out of support before .NET SDK 6. |
Here's a demo that shows the .NET Runtime regression without involving WCF. Sdk29734.csproj: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
</Project> Program.cs: using System;
using System.Reflection;
using System.Runtime.Loader;
namespace Sdk29734
{
public static class Program
{
static void Main()
{
var alc = new AssemblyLoadContext(name: @"Don't parse C:\");
Assembly assembly = alc.LoadFromAssemblyPath(typeof(Program).Assembly.Location);
Type type = assembly.GetType(typeof(Program).FullName);
MethodInfo method = type.GetMethod("Demo", BindingFlags.Public | BindingFlags.Static);
method.Invoke(null, null);
}
public static void Demo()
{
Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(Program).Assembly).Name);
IDemo proxy = DispatchProxy.Create<IDemo, Proxy>();
proxy.Method();
}
}
internal interface IDemo
{
void Method();
}
internal class Proxy : DispatchProxy
{
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
Console.WriteLine(targetMethod);
return null;
}
}
} Runs with .NET 6.0.12:
Fails with .NET 7.0.1:
|
Ugh, it isn't that simple. Even though one can set AssemblyName.Name =
I guess it blows up in unmanaged runtime/src/coreclr/vm/assembly.cpp Lines 400 to 406 in 97203d3
So, DispatchProxyGenerator needs to be fixed in some other way. The simplest change would be to make DispatchProxyGenerator always use Lines 120 to 129 in 97203d3
For debuggability though, it would be nicer to mangle the name, e.g. replace disallowed characters with underscores. |
https://github.com/dotnet/corefx/issues/34791, it was suggested:
which is what Assembly.LoadFile does:
Therefore, this bug can also be reproduced without explicitly specifying AssemblyLoadContext.Name. Sdk29734.csproj: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
</Project> Program.cs: using System;
using System.Reflection;
using System.Runtime.Loader;
namespace Sdk29734
{
public static class Program
{
static void Main()
{
Assembly assembly = Assembly.LoadFile(typeof(Program).Assembly.Location);
Type type = assembly.GetType(typeof(Program).FullName);
MethodInfo method = type.GetMethod(nameof(Demo), BindingFlags.Public | BindingFlags.Static);
method.Invoke(null, null);
}
public static void Demo()
{
Console.WriteLine(AssemblyLoadContext.GetLoadContext(typeof(Program).Assembly).Name);
IDemo proxy = DispatchProxy.Create<IDemo, Proxy>();
proxy.Method();
}
}
internal interface IDemo
{
void Method();
}
internal class Proxy : DispatchProxy
{
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
Console.WriteLine(targetMethod);
return null;
}
}
} Runs with .NET 6.0.12:
Fails with .NET 7.0.1:
|
MSBuild could be changed to work around this issue by not naming the assembly load contexts. Such a change could be helpful in case the AssemblyLoadContext fix is considered too risky for .NET 7. The custom MSBuild task cannot work around this issue by assigning null to AssemblyLoadContext.Name, because it is a read-only property. The custom MSBuild task could perhaps work around this issue by creating another AssemblyLoadContext without a name, and delegating the virtual methods to the AssemblyLoadContext that MSBuild created. Such a task would not be able to target netstandard2.0, though. Also, it might be difficult to forward the AssemblyLoadContext events to MSBuild's AssemblyLoadContext so that MSBuild can handle them. |
I agree with @KalleOlaviNiemitalo that this sounds like more of a runtime bug than MSBuild.
Agreed, though I would rather not do this as the info we put in the name seems handy. But not that handy, since it's only in the debugger. If we have to I wouldn't object too strongly. |
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-reflection Issue DetailsDescribe the bugAn msbuild task that calls a WCF service errors when running with dotNet 7.0. This occurred after a Visual Studio upgrade which delivered dotNet 7.0 alongside the already installed dotNet 6.0. To ReproduceHere I've attached a minimalist project that reproduces the issue: To see the problem follow these steps:
We are currently working around this problem by adding a global.json targeting the core 6.0 runtime and this can be demonstrated in the attached application by renaming the provided global.json.bak file. Before running the msbuild, start the WcfServiceLibrary so the service host is available and this will allow the mean the msbuild will run without error. Exceptions (if any)
Further technical detailsOutput from
Visual Studio version information:
|
Thank you for the broad investigation @KalleOlaviNiemitalo, it seems we don't need to use the ALC name or hash for the builder name, can just use the same name |
Is it feasible to publish the AssemblyLoadContext.Name to debuggers in some other way, so that they can find it if they have a reference to the generated assembly? AssemblyBuilder.DefineDynamicAssembly does not take an AssemblyLoadContext parameter, but it uses AssemblyLoadContext.CurrentContextualReflectionContext here: runtime/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs Lines 94 to 106 in 97203d3
So, DispatchPrpxy could use this API to place the generated assembly into the AssemblyLoadContext for which it was generated. However, I don't know what side effects that would have. Likely it's too risky for .NET 7. Alternatively, DispatchProxy could generate an AssemblyMetadataAttribute that carries the AssemblyLoadContext.Name. That would have lower risk. I don't know whether either of these would make it easy to view the ALC name in debuggers, especially in postmortem WinDbg + SOS. |
Probably this should be fixed with #62234 not in DispatchProxy
I would prefer replacing disallowed characters with underscores as you suggested above instead. I am still not sure how useful of having |
Describe the bug
An msbuild task that calls a WCF service errors when running with dotNet 7.0. This occurred after a Visual Studio upgrade which delivered dotNet 7.0 alongside the already installed dotNet 6.0.
To Reproduce
Here I've attached a minimalist project that reproduces the issue:
DotNet7BuildBug.zip
To see the problem follow these steps:
dotnet publish .\BuildTools\
from the root folder.dotnet msbuild .\Test.msbuild
. This highlights the issue being raised and raises the exception shown below.We are currently working around this problem by adding a global.json targeting the core 6.0 runtime and this can be demonstrated in the attached application by renaming the provided global.json.bak file. Before running the msbuild, start the WcfServiceLibrary so the service host is available and this will allow the mean the msbuild will run without error.
Exceptions (if any)
Further technical details
Output from
dotnet --info
:Visual Studio version information:
The text was updated successfully, but these errors were encountered: