Repository navigation
[dotnet-sdk-9.0.100-preview.3.24123.6] Windows SDK thrown "Non-blittable generic types cannot be marshaled" exception. #98977
Description
Description
Description:
When running 3rd party application with the latest .NET 9 build, applications cannot launch, or some functions don't work anymore. After investigating, we found the issue is caused by Windows sdk, which is thrown "Non-blittable generic types cannot be marshaled" exception.
Application Name: NatTypeTester, MyMoneyNet, FlowLauncher, ModernFlyouts, TextGrab, lively,CountdownNumberPuzzleSolver
OS: Windows 10 21H2
CPU: X64
.NET Build Number: dotnet-sdk-9.0.100-preview.3.24123.6
App & Source Location checking at: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1977811
Github Link:
https://github.com/HMBSbige/NatTypeTester
https://github.com/MoneyTools/MyMoney.Net
https://github.com/Flow-Launcher/Flow.Launcher
Reproduction Steps
Minimal Repro steps (Demo attached):MarshalDirectiveExceptionDemo.zip
The machine has dotnet-sdk-9.0.100-preview.3.24123.6 installed.
1.Create a new Console project.
2.Update TargetFramework in .csproject to "net9.0-windows10.0.22621.0", which is look like this:
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
3.Add following code into Program.cs file:
using Windows.Globalization;
using Windows.Media.Ocr;
List<Language> possibleOCRLanguages = OcrEngine.AvailableRecognizerLanguages.ToList();
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
- Launch the app.
Expected Result:
Expected behavior
App launch successfully.
Actual behavior
Actual Result:
Launch failed with error:
System.Runtime.InteropServices.MarshalDirectiveException
HResult=0x80131535
Message=Non-blittable generic types cannot be marshaled.
Source=WinRT.Runtime
StackTrace:
at ABI.System.Collections.Generic.IEnumerator`1.get_HasCurrent()
at ABI.System.Collections.Generic.IEnumerator`1.FromAbiHelper.MoveNext()
at ABI.System.Collections.Generic.IEnumerator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Program.<Main>$(String[] args) in E:\Demos\MarshalDirectiveExceptionDemo\MarshalDirectiveExceptionDemo\Program.cs:line 4
Regression?
Yes
Verify Scenarios:
1). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.101: Pass
2). Windows 10 21H2 AMD64 + dotnet-sdk-9.0.100-preview.2.24119.3: Pass
3). Windows 10 21H2 AMD64 + dotnet-sdk-9.0.100-preview.3.24123.6: Fail
4). Windows 10 21H2 AMD64 + dotnet-sdk-9.0.100-preview.3.24126.3: Fail
Known Workarounds
No response
Configuration
Dotnet Info:
.NET SDK:
Version: 9.0.100-preview.3.24123.6
Commit: 884fddb17a
Workload version: 9.0.100-manifests.06e7bcac
MSBuild version: 17.10.0-preview-24122-01+d4cb14fe4
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.100-preview.3.24123.6\
.NET workloads installed:
[wasm-tools]
Installation Source: VS 17.8.34601.278
Manifest Version: 9.0.0-preview.2.24123.1/9.0.100-preview.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100-preview.2\microsoft.net.workload.mono.toolchain.current\9.0.0-preview.2.24123.1\WorkloadManifest.json
Install Type: Msi
Host:
Version: 9.0.0-preview.2.24123.1
Architecture: x64
Commit: 99b7601
.NET SDKs installed:
9.0.100-preview.3.24123.6 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.0-preview.2.24121.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.0-preview.2.24123.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 9.0.0-preview.2.24122.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other information
@dotnet-actwx-bot @dotnet/compat
Metadata
Metadata
Assignees
Type
Projects
- StatusShow more project fieldsNo status
Activity
AaronRobinsonMSFT commentedon Feb 27, 2024
This regression seems to have been introduced by #97079.
AaronRobinsonMSFT commentedon Feb 27, 2024
@jkotas @jkoritzinsky I've not dug into the specifics of this yet. Does anything jump out to immediately?
/cc @manodasanW @hez2010
The failing stack is:
hez2010 commentedon Feb 27, 2024
We added a check here to block any calli which has a generic type context and requires runtime marshalling:
runtime/src/coreclr/vm/dllimport.cpp
Line 5049 in 151982a
Looking at the code
ABI.System.Collections.Generic.IEnumerator`1.HasCurrentin WinRT.Runtime:The
Get_HasCurrent_1is a calli with signaturedelegate* unmanaged[Stdcall]<System.IntPtr, out byte, int>underABI.System.Collections.Generic.IEnumerator<T>.Vftbl.Get_HasCurrent_1, so it's a calli under a generic context.Seems that the check here is too conservative.
There're three possible fixes:
delegate* unmanaged[Stdcall]<System.IntPtr, byte*, int>so that it's blittablejkotas commentedon Feb 27, 2024
There is no generic type in this signature. Why is this check failing on it in the first place? I agree that this check needs fixing.
It would be a good idea in any case. The marshalling is unnecessary and just a pure overhead.
jkotas commentedon Feb 27, 2024
We may want to strip the generic context when we are creating the calli cookie. Including the generic context in the calli cookie when it is not actually used by the signature prevents sharing the calli cookies for no good reason. It would not be surprised if it shows up as a perf regression in CsWinRT.
hez2010 commentedon Feb 27, 2024
The check failing because the
out byterequires runtime marshalling. We do the check if the calli is called under a generic context, regardless of whether the generic type is actually used in the calli signature. Previously we didn't do this check so theout byteis not being observed as an issue.jkotas commentedon Feb 27, 2024
I agree with your analysis. I think we should strip the unused generic context early when creating the calli cookie: #98977 (comment) . Would you like to submit a PR with the fix?
hez2010 commentedon Feb 27, 2024
Yes, but I'm afraid I'm not able to work on this until the next week. If it's urgent feel free to pick it up :)
But I think stripping the unused generic context early is not a correct fix, considering this valid case:
All generic context is used but it will fail due to the
ref int.Another fix is to check generic arguments only: hez2010@4b56160
But checking generic arguments only seems weird.
I think we can just remove the check completely as what NativeAOT does today.
Or we can make the check more conservative to check calli without a generic context as well, because we are already disallowing runtime marshalling for UnmanagedCallerOnly and reporting a compile error in C# (would requires fixes in CsWinRT).
@jkotas What do you think?
jkotas commentedon Feb 27, 2024
I think it is the desired behavior. We have said that we are not going to expand the scenarios where the built-in runtime marshaling kicks in. You example requires built-in runtime marshalling and it did not work before the change, so it should continue to not work after the change.
Strip unused generic type context for VASigCookie
Strip unused generic type context for VASigCookie
Strip unused generic type context for VASigCookie (#99026)
Junjun-zhao commentedon Mar 1, 2024
Verified this issue and it has been fixed on dotnet-sdk-9.0.100-preview.2.24129.6