Skip to content

Conversation

@davidwrighton
Copy link
Member

This fixes several issues:

  • A bug around usage of HasUnmanagedCallersOnlyAttribute in callstubgenerator.cpp (This is also a separate PR, since I'm convinced that fix is correct.)
  • Platform detection of IsBuiltInComEnabled in the presence of interpreter support
  • A bug in delegate creation around creating a delegate to a function which is marked with [UnmanagedCallersOnly]. I need to validate that we need to actually fix this or if the current check (which isn't on the slow path) can be adapted to work in the coreclr interpreter in some way.

- The HasUnmanagedCallersOnlyAttribute api is... not as accurate as I'd like. See comment in the code
- Fix an issue with platform detection where we are attempting to test COM interop tests with the interpreter enabled
- Fix an issue with creating a delegate to a method marked with an [UnmanagedCallersOnly] attribute. NOTE: This fix is probably not acceptable for long term usage as it injects a very expensive metadata lookup into the slow path delegate contruction logic.
@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 Dec 19, 2025
@davidwrighton
Copy link
Member Author

@AaronRobinsonMSFT @jkoritzinsky do you have an opinion on the check of HasUnmanagedCallersOnlyAttribute in the delegate constructor. We currently have a check for it in optimized delegate construction, which is almost always used by the JIT, but I need to know if we really need that to work, or if it's just a convenience feature that it fails.

@davidwrighton
Copy link
Member Author

/azp run runtime-interpreter

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

if (Nullable::IsNullableType(pMeth->GetMethodTable()))
COMPlusThrow(kNotSupportedException);

// Do not allow static methods with [UnmanagedCallersOnlyAttribute] to be a delegate target.
Copy link
Member

Choose a reason for hiding this comment

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

Most delegate constructor go via optimized path, so this is incomplete.

Our strategy has been to delay this check until the UnmanagedCallersOnly method is actually called and produce a fail-fast with a good error message in that case:

void ReversePInvokeBadTransition()

Copy link
Member Author

Choose a reason for hiding this comment

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

The optimized path already has this check. The question is should the slow path ALSO have the check.

Copy link
Member Author

Choose a reason for hiding this comment

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

The optimized path already has this check. The question is should the slow path ALSO have the check.

Copy link
Member

Choose a reason for hiding this comment

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

Where is this check on the optimized path?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's in the optimized delegate creation path called by the jit. I could replicate that if needed in the interpreter compiler. Search for the comment. I copied it verbatim.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's in the optimized delegate creation path called by the jit. I could replicate that if needed in the interpreter compiler. Search for the comment. I copied it verbatim.

Copy link
Member

Choose a reason for hiding this comment

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

I see it now. I think it is an oversight that we check for it on the fast path. It is inconsistent with the lazy check that we do everywhere else. For example, you can create delegate pointing to UMCO via reflection just fine (it will fail once you try to call it):

public class Program
{
    static void Main()
    {
        typeof(Program).GetMethod("Test").CreateDelegate<Action>();
    }

    [UnmanagedCallersOnly]
    public static void Test() { }
}

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

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants