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

Avoiding discarding exception details of MissingMethodException in RuntimeType.CreateInstanceImpl #108876

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

Takym
Copy link
Contributor

@Takym Takym commented Oct 15, 2024

I found the code that try { ... } catch (MissingMethodException) { invokeMethod = null; } and immediately later, re-throwing MissingMethodException if invokeMethod was null. This code removes stack trace information. So, I think debugging or analyzing gets difficult. I kept the code throwing MissingMethodException because binder.BindToMethod may return null.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Oct 15, 2024
}
catch (MissingMethodException) { invokeMethod = null; }

MethodBase? invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out object? state);
Copy link
Contributor

Choose a reason for hiding this comment

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

are there any tests that highlight the differences between the main branch and the pull request?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have tested by below steps:

  1. Build .NET Runtime
    1. Clone with the following command: git clone https://github.com/Takym/runtime.git -b AvoidingDiscardingExceptionDetails/2024_10
    2. Enter to the repository: cd runtime
    3. Run the build command: build
  2. Install .NET Runtime
    1. Open the installer directory: explorer .\artifacts\packages\Debug\Shipping
    2. Execute following installers:
      • dotnet-runtime-10.0.0-dev-win-x64.exe
      • dotnet-apphost-pack-10.0.0-dev-win-x64.msi
      • dotnet-targeting-pack-10.0.0-dev-win-x64.msi
  3. Create a new project with dotnet new console in a new empty directory.
  4. Rewrite Program.cs:
    using System.Globalization;
    using System.Reflection;
    
    try {
    	Activator.CreateInstance(typeof(object), BindingFlags.CreateInstance, new MyBinder(), null, null, null);
    } catch (Exception e) {
    	Console.WriteLine(e.ToString());
    }
    
    class MyBinder : Binder
    {
    	public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object?[] args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? names, out object? state)
    		=> throw new MissingMethodException("Hello, World!!");
    
    	public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo? culture)
    		=> throw new NotImplementedException();
    
    	public override object ChangeType(object value, Type type, CultureInfo? culture)
    		=> throw new NotImplementedException();
    
    	public override void ReorderArgumentArray(ref object?[] args, object state)
    		=> throw new NotImplementedException();
    
    	public override MethodBase? SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[]? modifiers)
    		=> throw new NotImplementedException();
    
    	public override PropertyInfo? SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type? returnType, Type[]? indexes, ParameterModifier[]? modifiers)
    		=> throw new NotImplementedException();
    }
  5. Running on .NET 9.0 or .NET 8.0: dotnet run
    System.MissingMethodException: Constructor on type 'System.Object' not found.
       at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
       at Program.<Main>$(String[] args)
    
  6. Running on .NET 10.0-dev: dotnet run --roll-forward LatestMajor
    System.MissingMethodException: Constructor on type 'System.Object' not found.
     ---> System.MissingMethodException: Hello, World!!
       at MyBinder.BindToMethod(BindingFlags bindingAttr, MethodBase[] match, Object[]& args, ParameterModifier[] modifiers, CultureInfo culture, String[] names, Object& state)
       at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
       --- End of inner exception stack trace ---
       at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
       at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
       at Program.<Main>$(String[] args)
    

Key Differences

  • My PR one contains all stack traces. So, it helps to analyze the error.
  • Also, you can check the inner exception message. This means you can know the root cause of the error.
  • I fixed this PR from no catching to rethrow for rewriting a message with the type's full name.
    • Initially, I removed the try-catch block to preserve the whole stack traces.
    • I got pointed out to include the original exception as an inner exception into a new exception to include the type full name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You should uninstall .NET 10.0-dev after behavior testing for your computer safety.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have tested by below steps:

That looks great, thank you. Also adding a unit test would be great, you can add the test in https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ActivatorTests.cs

Copy link
Contributor

Choose a reason for hiding this comment

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

Also adding a unit test would be great

yeah, that's exactly what i was getting at, so we can prevent this behavior from popping up again in the future. adding a unit test would be great.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a unit test in the commit e4a8824. I have pushed the commit to test it online with CI. Testing offline (local PC) is not finished yet. I will be trying to run it later.

Copy link
Member

@steveharter steveharter left a comment

Choose a reason for hiding this comment

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

Looks good; thanks!

Takym and others added 2 commits October 19, 2024 00:55
…/ActivatorTests.cs

Co-authored-by: Steve Harter <steveharter@users.noreply.github.com>
…/ActivatorTests.cs

Co-authored-by: Steve Harter <steveharter@users.noreply.github.com>
…/ActivatorTests.cs

Co-authored-by: kasperk81 <83082615+kasperk81@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Reflection community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants