Skip to content

RemoteExecutor field marshaling failure when in Live Unit Testing #14634

Open

Description

Summary

55 unit tests in the dotnet/maintenance-packages repo that try to use RemoteExecutor are failing due to unsupported field marshaling when attempting to run them with Live Unit Testing.

Note that all the unit tests pass without any issues in all other contexts:

  • When running them with regular Text Explorer.
  • When executed via CLI using dotnet test.
  • When executed in the CI (rolling builds or PRs).

@dotnet/interop-contrib @dotnet/runtime-infrastructure

Repro steps

  1. Open the solution using the build.cmd -vs MaintenancePackages.sln command.
  2. Test menu -> Live Unit Testing -> Start. If asked, choose a location for the lut folder. Wait for the tests to finish.
  3. Go to the Live Unit Testing tab. Select any of the failing tests. The callstack will look something like this:
 System.Buffers.ArrayPool.Tests.ArrayPoolUnitTests.RentBufferFiresRentedDiagnosticEvent

  Message: 
System.ArgumentException : Field marshaling is not supported by Invoke: CS$InstrumentationPayload1

  Stack Trace: 
RemoteExecutor.GetMethodInfo(Delegate d) line 596
RemoteExecutor.Invoke(Action method, RemoteInvokeOptions options) line 118
ArrayPoolTest.RemoteInvokeWithTrimming(Action method, Int32 timeout) line 48
ArrayPoolUnitTests.RentBufferFiresRentedDiagnosticEvent() line 403

The exception is being thrown in line 596:

private static MethodInfo GetMethodInfo(Delegate d)
{
// RemoteInvoke doesn't support marshaling state on classes associated with
// the delegate supplied (often a display class of a lambda). If such fields
// are used, odd errors result, e.g. NullReferenceExceptions during the remote
// execution. Try to ward off the common cases by proactively failing early
// if it looks like such fields are needed.
if (d.Target != null)
{
// The only fields on the type should be compiler-defined (any fields of the compiler's own
// making generally include '<' and '>', as those are invalid in C# source). Note that this logic
// may need to be revised in the future as the compiler changes, as this relies on the specifics of
// actually how the compiler handles lifted fields for lambdas.
Type targetType = d.Target.GetType();
foreach (var fi in targetType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
if (fi.Name.IndexOf('<') == -1)
{
throw new ArgumentException($"Field marshaling is not supported by {nameof(Invoke)}: {fi.Name}");

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

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions