Fix Apple NativeAOT test harness crash from string P/Invoke marshalling#130341
Conversation
AppleTestRunner.cs declares the mono_ios_set_summary and mono_ios_append_output __Internal P/Invokes with a string parameter. This file is compiled into every library test assembly. Several of those assemblies apply [assembly: DisableRuntimeMarshalling] through Common/src/DisableRuntimeMarshalling.cs, which disallows non-blittable P/Invoke marshalling. Under that attribute the NativeAOT compiler cannot marshal the string argument, even with [MarshalAs(UnmanagedType.LPUTF8Str)], so it emits a stub that throws MarshalDirectiveException. The harness aborts on startup before any test runs, failing every affected work item on the Apple NativeAOT test legs. Change the extern declarations to take a blittable IntPtr and convert the string to a null-terminated UTF-8 buffer in managed code with Marshal.StringToCoTaskMemUTF8, matching the native const char* signature in main-console.m. A blittable P/Invoke requires no runtime marshalling, so it compiles and runs under DisableRuntimeMarshalling and remains correct on Mono and NativeAOT. Fixes dotnet#130219 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
There was a problem hiding this comment.
Pull request overview
This PR updates the Apple NativeAOT library test harness (SimpleTestRunner) to avoid unsupported string marshalling in __Internal P/Invokes by switching the native imports to a blittable IntPtr signature and performing explicit UTF-8 allocation/free in managed code. This aligns the managed interop with the native const char* functions used by the AppleAppBuilder template and prevents the harness from aborting before any tests execute on Apple NativeAOT legs.
Changes:
- Replace
string-typedDllImport("__Internal")declarations withIntPtr-typed native entrypoints. - Add managed wrappers that convert
stringto a null-terminated UTF-8 buffer viaMarshal.StringToCoTaskMemUTF8and free it withMarshal.FreeCoTaskMem.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/Common/tests/AppleTestRunner/AppleTestRunner.cs | Switches mono_ios_* P/Invokes to blittable IntPtr and adds UTF-8 allocation/free wrappers to avoid runtime marshalling. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 0
|
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Yes, this is not supposed to work and I don't think it works with CoreCLR either. The fact it works on Mono is a bit concerning because DisableRuntimeMarshalling is supposed to fully disable it. I guess if we didn't run into issues so far, it's probably fine for one more release. Does |
[LibraryImport] should work, but the generated stub is unsafe, which is why I went with it. If you prefer [LibraryImport] for consistency, I am happy to switch it. |
The APIs you are calling directly are unsafe too, and they will require unsafe annotations in not-too-distant future as well. |
Replace the manual `IntPtr` plus `Marshal.StringToCoTaskMemUTF8` marshalling of `mono_ios_set_summary` and `mono_ios_append_output` with source-generated `[LibraryImport]` using `StringMarshalling.Utf8`. The generator emits a blittable `byte*` inner P/Invoke and performs the UTF-8 conversion in managed code, so no runtime string marshalling crosses the P/Invoke boundary. This keeps the harness correct under `[assembly: DisableRuntimeMarshalling]` on NativeAOT and on Mono. The generated stubs require unsafe code, so `AllowUnsafeBlocks` is enabled for the harness project and the NativeAOT iOS-like test build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/ba-g unrelated extra-platforms failures, no marshalling Native AOT errors on Apple mobile |
Description
The Apple NativeAOT test harness aborts on startup with
MarshalDirectiveExceptionbefore any test runs. Itsmono_ios_set_summaryandmono_ios_append_output__InternalP/Invokes take astring, and the harness file is compiled into library test assemblies that apply[assembly: DisableRuntimeMarshalling]throughsrc/libraries/Common/src/DisableRuntimeMarshalling.cs. Under that attribute the NativeAOT compiler disallows non-blittable string marshalling even with[MarshalAs(UnmanagedType.LPUTF8Str)], so it emits a stub that throws at startup. This change switches the externs to a blittableIntPtrand converts the string to a null-terminated UTF-8 buffer in managed code withMarshal.StringToCoTaskMemUTF8, matching the nativeconst char*insrc/tasks/AppleAppBuilder/Templates/main-console.m. A blittable P/Invoke needs no runtime marshalling and stays correct on Mono and NativeAOT.Fixes #130219.