dotnet/diagnostics

dotnet trace not working for MAUI application using EF Core

jakob-bmd opened this issue · 6 comments

Description

Simple MAUI test application can be seen here.

When I press enter to stop tracing a MAUI application, the CLI outputs the following exception:

[ERROR] Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException: Could not send Stop command. The target process may have exited.
   at Microsoft.Diagnostics.NETCore.Client.EventPipeSession.Stop() in /_/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/EventPipeSession.cs:line 61
   at Microsoft.Diagnostics.Tools.Trace.CollectCommandHandler.Collect(CancellationToken ct, IConsole console, Int32 processId, FileInfo output, UInt32 buffersize, String providers, String profile, TraceFileFormat format, TimeSpan duration, String clrevents, String clreventlevel, String name, String diagnosticPort, Boolean showchildio, Boolean resumeRuntime, String stoppingEventProviderName, String stoppingEventEventName, String stoppingEventPayloadFilter, Nullable`1 rundown) in /_/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs:line 406

The application runs on an Android emulator which uses EF Core with a SQLite database.
During debugging I found out that outcommenting methods calling Entity Framework Core functionalities solve the issue (see test application - MainViewModel.cs line 36-39).

Steps to reproduce:

  • download test app
  • start visual studio and emulator
  • switch to TestMauiApp directory `
  • build app in CLI via dotnet build -f net8.0-android -t:Install -c Release -p:AndroidEnableProfiler=true
  • Connect dsrouter with app by entering dotnet-dsrouter android-emu
    • note the DOTNET_DiagnosticPorts (e.g. 10.0.0.2:9000)
    • note the dotnet-dsrouter pid (e.g. 3248)
  • open another (adb) command prompt and enter following command (important: use previously noted DOTNET_DiagnosticPorts): adb shell setprop debug.mono.profile '10.0.2.2:9000,suspend,connect'
  • enter in 2nd cli dotnet-trace collect -p 3248 --format speedscope

Expected behavior:

  • tracing stops and generates speedscope file

Configuration

  • Is this related to a specific tool?
    => dotnet trace
  • What OS and version, and what distro if applicable?
    => application is running on Android,
  • What is the architecture (x64, x86, ARM, ARM64)?
    => screenshot of the emulator
    image.
  • Do you know whether it is specific to that configuration?
    => No
  • Are you running in any particular type of environment? (e.g. Containers, a cloud scenario, app you are trying to target is a different user)
    => No
  • Is it a self-contained published application?
    => I'm not aware of the meaning of this. But I think it is
  • What's the output of dotnet info
.NET SDK:
 Version:           8.0.200
 Commit:            438cab6a9d
 Workload version:  8.0.200-manifests.e575128c

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.200\

.NET workloads installed:
 [android]
   Installation Source: VS 17.9.34622.214
   Manifest Version:    34.0.52/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.android\34.0.52\WorkloadManifest.json
   Install Type:        FileBased

 [maui-windows]
   Installation Source: VS 17.9.34622.214
   Manifest Version:    8.0.6/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maui\8.0.6\WorkloadManifest.json
   Install Type:        FileBased

 [maccatalyst]
   Installation Source: VS 17.9.34622.214
   Manifest Version:    17.2.8004/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maccatalyst\17.2.8004\WorkloadManifest.json
   Install Type:        FileBased

 [ios]
   Installation Source: VS 17.9.34622.214
   Manifest Version:    17.2.8004/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.ios\17.2.8004\WorkloadManifest.json
   Install Type:        FileBased


Host:
  Version:      8.0.2
  Architecture: x64
  Commit:       1381d5ebd2

.NET SDKs installed:
  8.0.200 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

dotnet tool list -g result:

Package Id           Version         Commands
----------------------------------------------------
dotnet-counters      8.0.510501      dotnet-counters
dotnet-dsrouter      8.0.510501      dotnet-dsrouter
dotnet-ef            8.0.2           dotnet-ef
dotnet-gcdump        8.0.510501      dotnet-gcdump
dotnet-trace         8.0.510501      dotnet-trace

Regression?

  • Did this work in a previous build or release - either of the tool or of the .NET runtime being used?
    => don't know

Other information

  • test repo: https://github.com/jakob-bmd/maui_ef_core_dotnet_trace
  • .nettrace file is in the linked repo.
  • tombstone file of the TestMauiApp is also in the repo
  • this might have something todo with this issue, but has been no solution apart from dotnet update.
    The same error message can be found in the tombstone_10 file (line 2900) in the linked repo.
  • the issue also occurs on a real device (tested with Samsung Galaxy XCover5)
  • I'm not aware of any workarounds

Hi @jakob-bmd, thanks for opening up this issue and providing a repro and details about your build. This did hit the same assert failure as dotnet/runtime#93687 (not sure if they're for the same reasons), and it is a mono runtime failure. While closing the EventPipe session (Enter | ctrl+c in dotnet-trace), rundown events are fired, and in this instance, an edge case was being hit while emitting rundown method events.

There is a fix dotnet/runtime#99617, and until it is merged/backported, a workaround would be to build the runtime locally with that change and including the build target in your project's .csproj demonstrated here

Note: I was also able to circumvent the mono EventPipe rundown crash by omitting these lines in your program https://github.com/jakob-bmd/maui_ef_core_dotnet_trace/blob/f9cea586b0a2ac91ee9f89d748973dc16ba405be/TestMauiApp/MainViewModel.cs#L31-L38, but those seem crucial to your project.

Thank you for the PR/fix!
I'll wait for the (9.0.0) release then. The workaround is hardly applicable in our case.

I have been running into the same issue for the last couple of weeks, likely due to dynamic method execution, so I am really happy to see progress in this issue 😃. I want to try out the PR and not wait for the release, to profile some changes I have in my codebase. What would be the steps to do so? I am currently profiling on either an iOS or an Android device.

Hi @jurganson!

To try out the changes before waiting for .NET 8.0.5, which is the proposed milestone when dotnet/runtime#99712 will be merged, you'll need to 1) build the runtime for your platforms iOS/Android locally with the relevant change, and then 2) use the locally built runtime pack in your projects using a target that performs the replacing.

  1. Build the runtime for iOS/Android

After cloning the repo, there are different prerequisites for building on each OS.
If you don't mind building the latest runtime, stay on the main branch, otherwise feel free to choose from one of the release branches or one of the tags.
Screenshot 2024-04-08 at 10 28 05 AM
After you've selected what branch or tag you want to build from, make the following change https://github.com/dotnet/runtime/pull/99617/files and continue with the building mono for iOS/Android
./build.sh -s mono+libs -os ios -arch <your_ios_architecture> -c <Debug|Release>
./build.sh -s mono+libs -os android -arch <your_android_architecture> -c <Debug|Release>

Afterwards, you should see in your local artifacts
<repo_root>/artifacts/bin/microsoft.netcore.app.runtime.ios-<arch>/<config>
<repo_root>/artifacts/bin/microsoft.netcore.app.runtime.android-<arch>/<config>

  1. Use the locally built runtime packs in your projects using a target like the one here
    For example, if you built android arm64 debug, your target would look like this in the project
<Target Name="UpdateRuntimePack" AfterTargets="ResolveFrameworkReferences">
        <ItemGroup>
            <ResolvedRuntimePack PackageDirectory="<RUNTIME_GIT_ROOT>/artifacts/bin/microsoft.netcore.app.runtime.android-arm64/Debug" Condition="'%(ResolvedRuntimePack.FrameworkName)' == 'Microsoft.NETCore.App'" />
        </ItemGroup>
</Target>

@jurganson I got an email notification that you commented here asking about the dotnet runtime version. I'm not seeing it here, but I wanted to respond just in case it's still an unanswered question.

You'll have to rebuild your application, either with 1) an SDK that contains the change or 2) a target added to your .csproj that uses a locally built runtimepack from building dotnet/runtime.

From the available Dotnet SDKs to download/install, currently only main from https://github.com/dotnet/installer#table should contain the fix, so if you need to target .NET 8, you will have to either wait for .NET 8.0.5 or build the runtimepacks locally to inject into your .csproj