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

[android] arm64 running on x64 emulator unexpected FPSIMD_MAGIC assert #62201

Closed
lambdageek opened this issue Nov 30, 2021 · 25 comments · Fixed by #89467
Closed

[android] arm64 running on x64 emulator unexpected FPSIMD_MAGIC assert #62201

lambdageek opened this issue Nov 30, 2021 · 25 comments · Fixed by #89467

Comments

@lambdageek
Copy link
Member

lambdageek commented Nov 30, 2021

Recent versions (API 30 x86_64) of the Android emultator can run arm64 binaries on an x86_64 emultator using some kind of binary translation. When an app is running in this environment, it looks like the struct sigcontext __reserved field is not laid out with the fpsimd_context first.

As a result this code asserts:

struct fpsimd_context *fpctx = (struct fpsimd_context*)&((ucontext_t*)sigctx)->uc_mcontext.__reserved;
int i;
g_assert (fpctx->head.magic == FPSIMD_MAGIC);

Linux kernel sigcontext __reserved note

Instead of looking at the first context in __reserved and asserting that it has FPSIMD_MAGIC, we should check head.magic == FPSIMD_MAGIC and if not, move forward by head.size bytes and try again until we see head.magic == 0 (the last block).

Potentially we can assume that the offset won't change between calls to mono_sigctx_to_monoctx and cache the pre-computed offset (and assert that the magic is the right one).


Reproduction steps for XA:

  1. Turn off fast deployment by adding <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> to the csproj file
  2. Remove definition for $(AndroidSupportedAbis) if there is any in the .csproj file
  3. Add <RuntimeIdentifiers>android-arm;android-arm64</RuntimeIdentifiers> to the csproj file
  4. Build and run the app in Release mode on x86_64 emulator crashes using dotnet build -c Release -t:Run
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Nov 30, 2021
@ghost
Copy link

ghost commented Nov 30, 2021

Tagging subscribers to 'arch-android': @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Issue Details

Recent versions (API 30 x86_64) of the Android emultator can run arm64 binaries on an x86_64 emultator using some kind of binary translation. When an app is running in this environment, it looks like the struct sigcontext __reserved field is not laid out with the fpsimd_context first.

As a result this code asserts:

struct fpsimd_context *fpctx = (struct fpsimd_context*)&((ucontext_t*)sigctx)->uc_mcontext.__reserved;
int i;
g_assert (fpctx->head.magic == FPSIMD_MAGIC);

Instead of looking at the first context in __reserved and asserting that it has FPSIMD_MAGIC, we should check head.magic == FPSIMD_MAGIC and if not, move forward by head.size bytes and try again until we see head.magic == 0 (the last block).

Potentially we can assume that the offset won't change between calls to mono_sigctx_to_monoctx and cache the pre-computed offset (and assert that the magic is the right one).


Reproduction steps for XA:

  1. Turn off fast deployment
  2. $(AndroidSupportedAbis) is blank, just not in the .csproj file
  3. Defaults to armeabi-v7a;arm64-v8a
  4. Running on x86_64 emulator crashes
Author: lambdageek
Assignees: -
Labels:

arch-arm64, os-android, untriaged, area-VM-meta-mono

Milestone: -

@lambdageek
Copy link
Member Author

@jonathanpeppers can you verify/update the repro steps

/cc @grendello

@lambdageek lambdageek added this to the .NET 6.0-MAUI milestone Nov 30, 2021
@jonathanpeppers
Copy link
Member

  • Build & debug this app on an x86_64 API 30 emulator: App34.zip

I think as long as you're using VS 2022, the issue should repro.

To workaround, you can either go to Project properties | Android Options | Advanced, and enable all ABIs:

image

Or Release builds also happen to work, not sure why.

@akoeplinger
Copy link
Member

Moving to 7.0

@akoeplinger akoeplinger modified the milestones: 6.0.MAUI, 7.0.0 Mar 17, 2022
@jeffschwMSFT jeffschwMSFT removed the untriaged New issue has not been triaged by the area owner label Mar 28, 2022
@SamMonoRT SamMonoRT modified the milestones: 7.0.0, 8.0.0 Aug 12, 2022
@SamMonoRT
Copy link
Member

cc @fanyang-mono -- moving to 8.0.0

@Falco20019
Copy link

Falco20019 commented Jun 20, 2023

Setting AndroidSupportedAbis is not supported anymore as workaround starting with .NET 6. It will be force-overwritten here:

https://github.com/xamarin/xamarin-android/blob/main/src/Xamarin.Android.Build.Tasks/Tasks/RuntimeIdentifierToAbi.cs#L29-L34

Setting <RuntimeIdentifiers>android-arm64;android-x64</RuntimeIdentifiers> fails at runtime, since native libs are missing (grpc_csharp_ext in my case, which is why I would need to use android-arm64 only but with x86_64 being allowed as emulator).

Using Release mode but without success. We used android-x86 in the past, which is not supported on Android 12+ anymore.

@fanyang-mono
Copy link
Member

I couldn't reproduce this issue anymore. Here is what I've tried on API 30 x86_64 emulator using

dotnet new android

Modify the csprroj file to add
    <AndroidSupportedAbis>armeabi-v7a;arm64-v8a</AndroidSupportedAbis>
    <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>

dotnet build -c Release/Debug -r android-arm64 -t:Run --self-contained

The app worked fine.

Here is the dotnet version that I used

.NET SDK:
 Version:   8.0.100-preview.6.23330.14
 Commit:    ba97796b8f

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  13.4
 OS Platform: Darwin
 RID:         osx.13-x64
 Base Path:   /Users/yangfan/Documents/work/dotnet8/sdk/8.0.100-preview.6.23330.14/

.NET workloads installed:
 [android]
   Installation Source: SDK 8.0.100-preview.6
   Manifest Version:    34.0.0-preview.3.224/8.0.100-preview.3
   Manifest Path:       /Users/yangfan/Documents/work/dotnet8/sdk-manifests/8.0.100-preview.3/microsoft.net.sdk.android/WorkloadManifest.json
   Install Type:        FileBased

Host:
  Version:      8.0.0-preview.6.23329.7
  Architecture: x64
  Commit:       5340be2ccc

.NET SDKs installed:
  8.0.100-preview.6.23330.14 [/Users/yangfan/Documents/work/dotnet8/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 8.0.0-preview.6.23329.11 [/Users/yangfan/Documents/work/dotnet8/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 8.0.0-preview.6.23329.7 [/Users/yangfan/Documents/work/dotnet8/shared/Microsoft.NETCore.App]

@Falco20019 Could you try this version of dotnet to see if the issue is still there? If so, could you provide a reproduction app?

@Falco20019
Copy link

I can have a test with the SDK, but I will need to target .NET 6 as the application is bound to that right now. Preparation for .NET 8 has not yet started since our company IT requires us to get approval to use Preview releases of software. We currently build using latest .NET 7 SDK targeting .NET 6.

@fanyang-mono
Copy link
Member

@Falco20019 Unfortunately, we've dropped the supporte for .NET6 alreaday. See detailes at https://dotnet.microsoft.com/en-us/platform/support/policy/maui. I went ahead and tried targeting .NET7. I couldn't reproduce the issue. Is there anything else that you would like me to try to reproduce the issue?

@Falco20019
Copy link

Falco20019 commented Jul 17, 2023

@fanyang-mono Thanks for letting me know about the lifecycle. Since we are not actively using MAUI itself, I was not aware. But since the code path I mentioned hasn't changed in 2 years, it should still trigger XA0035.

Make sure to also set the RuntimeIdentifiers flag. -r is only setting RuntimeIdentifier (singular, not plural). Since our application limits the identifiers possible, that one is set. And the combination of RuntimeIdentifiers and AndroidSupportedAbis seems to be what triggers the error starting with .NET 5 and most probably also still in .NET 8 Preview 6. The code block causing it that I linked even has a note at the top mentioning that this should be fixed once multiple RIDs are supported.

You also need to add native libs to see if they are missing or not. The app itself started fine, but the native libs were missing. We needed the android-arm64 build to include the arm64-v8a and x86_64 libs, because on the x86_64 emulator, the arm64-v8a libs were not loaded.

The emulator I tried was the official API 31 from Google through the device manager.

@fanyang-mono
Copy link
Member

@Falco20019 What are the values your project set each of RuntimeIdentifiers and AndroidSupportedAbis to?

@fanyang-mono
Copy link
Member

I was able to reproduce the crash now. This is related to https://github.com/xamarin/xamarin-android/issues/7444 and more detailed reproduction steps could be found there.

@fanyang-mono
Copy link
Member

To clarify, I was only able to reproduce the ICU caused crash mentioned in https://github.com/xamarin/xamarin-android/issues/7444 by adding var dateString = DateTime.Now.ToString(CultureInfo.CreateSpecificCulture("en-US")); to OnCreate in MainActivity.cs. I was not able to reproduce the FPSIMD_MAGIC assert with an android template app.

@fanyang-mono
Copy link
Member

@Falco20019 Did you hit the FPSIMD_MAGIC assert or other asserts which indicated native library missing?

@Falco20019
Copy link

Falco20019 commented Jul 19, 2023

I hit the FPSIMD_MAGIC assert, which is how I found this ticket. I will try to give you reproduction steps next week as I'm sadly already fully planned out that week with other tasks.

Regarding support, the policy also states that the workload is independent of the .NET SDK and these are the workloads we currently use for targeting Android on .NET 6:

Installierte Workload-ID      Manifestversion        Installationsquelle
-----------------------------------------------------------------------------------
android                       33.0.68/7.0.100        SDK 7.0.300, VS 17.6.33829.357
ios                           16.4.7067/7.0.100      VS 17.6.33829.357
maui-ios                      7.0.86/7.0.100         VS 17.6.33829.357
maui-windows                  7.0.86/7.0.100         VS 17.6.33829.357
maui-maccatalyst              7.0.86/7.0.100         VS 17.6.33829.357
maccatalyst                   16.4.7067/7.0.100      VS 17.6.33829.357
maui-android                  7.0.86/7.0.100         VS 17.6.33829.357

We use .NET SDK 7.0.306 while targeting net6.0-android.

@fanyang-mono
Copy link
Member

@Falco20019 On this page (https://dotnet.microsoft.com/en-us/platform/support/policy/maui), it listed the supporting timeframe for workloads not sdk. The support for .NET MAUI 6 has expired on May 8, 2023, which is what your product is currently targeting at.

Looking forward to your reproduction steps. :)

@Falco20019
Copy link

But isn't using the workload maui-android in version 7.0.86 using .NET MAUI 7? Even if targeting net6.0-android? There is no separate workload installed for .NET 6 and also when I do a diagnosis output of the build it says it's using the targets from 7.x.

That's why I was wondering about the lifecycle note. The workload used is the latest stable and should therefore not be .NET MAUI 6 independent of the target SDK. At least to my understanding.

@fanyang-mono
Copy link
Member

@jonathanpeppers Could you please provide some insights here, regarding to @Falco20019's workflow?

@jonathanpeppers
Copy link
Member

There is no separate workload installed for .NET 6

If you specify net6.0-android in your project, we bring in .NET 6 packs for you automatically, for example:

We install the Microsoft.Android.Sdk.* pack for .NET 6 alongside the .NET 7 workload to support this. While the targeting and runtime packs are restored from NuGet on demand.

Even if you're building with the .NET 7 SDK, you need to specify net7.0-android in your project to use the latest supported packs. We have a build warning coming in .NET 7.0.400, but it was just a little late in the release cycle:

dotnet/sdk#32426

@Falco20019
Copy link

Falco20019 commented Jul 21, 2023

Thanks for the clarifications to both of you! I also highly appreciate the addition of the EOL warning in the upcoming patch :) This will bring the difference in the supported lifecycle to more people's attention.

Your input also helped me to already adjust our internal decisions. While we earlier decided to go LTS, we will now try to stay on LATEST instead.

I try to send in the recreational steps by mid of next week.

@Falco20019
Copy link

I was able to create some really minimal recreational steps, not even depending on any external libraries.

  1. Create new default Android App using dotnet new android
  2. Add <RuntimeIdentifiers>android-arm64</RuntimeIdentifiers> to csproj
  3. Run on default emulator [Pixel (+Store) x86_64 Android 13.0 with Google APIs] through Visual Studio 2022

This will reproducibly result in the app failing, even when targeting .NET MAUI 7:

Time	Device Name	Type	PID	Tag	Message
07-21 07:36:31.534	android_emulator_33	Error	8151	com.companyname.AndroidApp4	* Assertion at /__w/1/s/src/mono/mono/utils/mono-context.c:539, condition `fpctx->head.magic == FPSIMD_MAGIC' not met

I tested it against the x86_64 emulators for API 30, 31 and 33 and all are crashing.

If I try it with dotnet build -c Debug -r android-arm64 -t:Run --self-contained like you did, it seems to work. So it seems it might be related to the debugger.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 25, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 27, 2023
@Falco20019
Copy link

Just for my understanding, the Mono stuff is compiled into the .NET runtime (not Microsoft.Android.Sdk.Windows or Microsoft.Android.Runtime.31.android-arm64) and therefore only end up in APKs targeting net7.0-android or .NET 8 Preview without option to bring it in through NuGet packages, right?

We understand that .NET MAUI 6 is EOL and don't expect any backport. Just checking for workarounds until we can switch to .NET 8 in November as it was decided to not invest any more time into supporting .NET 7 so shortly before .NET MAUI 8 gets released.

@akoeplinger
Copy link
Member

and therefore only end up in APKs targeting net7.0-android or .NET 8 Preview without option to bring it in through NuGet packages, right?

That's correct.

@fanyang-mono
Copy link
Member

The fix to this issue has been backported to .NET7 servicing and will be available soon.

@Falco20019
Copy link

Falco20019 commented Aug 8, 2023

https://github.com/dotnet/runtime/blob/v7.0.10/src/mono/mono/utils/mono-context.c#L543 seems to not contain your change (whereas main does) and #89568 has the milestone 7.0.11. If I understand the process correctly, changes are done to release/7.0-staging which is basically vNext+1 and ends up in release/7.0 once vNext was released, correct?

The currently released version is 7.0.9. I assume this will then come with 7.0.11 expected to release on September 12th, right? That would be a bummer since it means another month of not being able to test anything.

We will try to use -t:Run locally in the meanwhile, but due to the way we build our APK packages using a CI pipeline, that's harder and we might need some workarounds to even build locally.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants