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

Initializing SentrySdk Crashes when running with AndroidEnableAssemblyCompression = false in Release mode #3920

Open
Cheesebaron opened this issue Jan 27, 2025 · 6 comments
Assignees
Labels
Blocked Bug Something isn't working Framework: MAUI

Comments

@Cheesebaron
Copy link
Contributor

Package

Sentry.Extensions.Logging

.NET Flavor

.NET

.NET Version

9.0.100

OS

Android

SDK Version

5.0.0 + 5.0.1

Self-Hosted Sentry Version

No response

Steps to Reproduce

We have an application which only exposes a Service. This is normally bound to by some of our other applications to exchange information.

We upgraded to .NET 9 and Sentry to 5.0.1 recently, and we see a weird crash when the Service starts, we initially thought it was some of our dependencies that were causing the issue, but seems like even when moving the initialization code to MainApplication it throws the following exception at startup:

FATAL EXCEPTION: main
Process: dk.trackman.range.kiosk.virtualgolfmediator, PID: 1976
android.runtime.JavaProxyThrowable: [System.Security.Cryptography.CryptographicException]: Cryptography_ConcurrentUseNotSupported
	at System.Security.Cryptography.ConcurrencyBlock.Enter + 0x1a(Unknown Source)
	at System.Security.Cryptography.HashProviderDispenser+EvpHashProvider.FinalizeHashAndReset + 0x0(Unknown Source)
	at System.Security.Cryptography.HashProvider.FinalizeHashAndReset + 0x13(Unknown Source)
	at System.Security.Cryptography.SHA1+Implementation.HashFinal + 0x0(Unknown Source)
	at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize + 0x0(Unknown Source)
	at System.Security.Cryptography.HashAlgorithm.ComputeHash + 0x22(Unknown Source)
	at Sentry.Internal.Extensions.HashExtensions.GetHashString + 0x12(Unknown Source)
	at Sentry.Internal.InstallationIdHelper.TryGetPersistentInstallationId + 0x46(Unknown Source)
	at Sentry.Internal.InstallationIdHelper.TryGetInstallationId + 0x3b(Unknown Source)
	at Sentry.SentryOptions.<.ctor>b__346_0 + 0x6(Unknown Source)
	at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ViaFactory + 0x44(Unknown Source)
	at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ExecutionAndPublication + 0x22(Unknown Source)
	at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].CreateValue + 0x74(Unknown Source)
	at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].get_Value + 0xa(Unknown Source)
	at Sentry.SentryOptions.get_InstallationId + 0x0(Unknown Source)
	at Sentry.GlobalSessionManager.StartSession + 0x3c(Unknown Source)
	at Sentry.Internal.Hub.StartSession + 0x3c(Unknown Source)
	at Sentry.Integrations.AutoSessionTrackingIntegration.Register + 0x8(Unknown Source)
	at Sentry.Internal.Hub..ctor + 0xf8(Unknown Source)
	at Sentry.SentrySdk.InitHub + 0x7d(Unknown Source)
	at Sentry.SentrySdk.Init + 0x0(Unknown Source)
	at TrackMan.VirtualGolfMediator.Droid.MainApplication.OnCreate + 0x23(Unknown Source)
	at Android.App.Application.n_OnCreate + 0x8(Unknown Source)
	at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V + 0x5(Unknown Source)
	at crc6449c06082aa7b0d2b.MainApplication.n_onCreate(Native Method)
	at crc6449c06082aa7b0d2b.MainApplication.onCreate(MainApplication.java:24)
	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)
	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6712)
	at android.app.ActivityThread.access$1300(ActivityThread.java:237)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:223)
	at android.app.ActivityThread.main(ActivityThread.java:7656)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

This is when we call the following code in MainApplication.OnCreate:

var options = new SentryLoggingOptions
{
    Dsn = "our-dsn-here",
    MinimumEventLevel = LogLevel.Critical
};
options.DisableUnobservedTaskExceptionCapture();
SentrySdk.Init(options);

Interestingly we had the IsGlobalModeEnabled = false set in options then it seemd to crash differently at startup with:

FATAL EXCEPTION: main
Process: dk.trackman.range.kiosk.virtualgolfmediator, PID: 2184
android.runtime.JavaProxyThrowable: [System.Threading.LockRecursionException]: LockRecursionException_RecursiveReadNotAllowed
	at System.Threading.ReaderWriterLockSlim.TryEnterReadLockCore + 0x56(Unknown Source)
	at System.Threading.ReaderWriterLockSlim.TryEnterReadLock + 0x0(Unknown Source)
	at System.Threading.ReaderWriterLockSlim.TryEnterReadLock + 0x7(Unknown Source)
	at System.Threading.ReaderWriterLockSlim.EnterReadLock + 0x0(Unknown Source)
	at Sentry.Scope.get_Transaction + 0x0(Unknown Source)
	at Sentry.Scope.set_TransactionName + 0x7(Unknown Source)
	at Sentry.Scope.Apply + 0x1a8(Unknown Source)
	at Sentry.Scope.Apply + 0x9(Unknown Source)
	at Sentry.Scope.Clone + 0x1e(Unknown Source)
	at Sentry.Internal.SentryScopeManager.PushScope + 0x76(Unknown Source)
	at Sentry.Internal.SentryScopeManager.PushScope + 0x0(Unknown Source)
	at Sentry.Internal.Hub.PushScope + 0x6(Unknown Source)
	at Sentry.Internal.Hub..ctor + 0xc6(Unknown Source)
	at Sentry.SentrySdk.InitHub + 0x7d(Unknown Source)
	at Sentry.SentrySdk.Init + 0x0(Unknown Source)
	at TrackMan.VirtualGolfMediator.Droid.MainApplication.OnCreate + 0x3c(Unknown Source)
	at Android.App.Application.n_OnCreate + 0x8(Unknown Source)
	at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V + 0x5(Unknown Source)
	at crc6449c06082aa7b0d2b.MainApplication.n_onCreate(Native Method)
	at crc6449c06082aa7b0d2b.MainApplication.onCreate(MainApplication.java:24)
	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)
	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6712)
	at android.app.ActivityThread.access$1300(ActivityThread.java:237)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:223)
	at android.app.ActivityThread.main(ActivityThread.java:7656)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

I've managed to narrow this down to the project property AndroidEnableAssemblyCompression which we had set to false. If I recall correctly, we set this to work around an issue in an earlier version of the .NET Android workloads that would crash the App at startup trying to unpack the assemblies.

My question is, why does this cause Sentry to crash at startup when this property is set to false. Seemingly it mainly happens in Sentry code, because when we remove SentrySdk.Init the rest of the App seems to work OK.

Here is a repo with the issue: https://github.com/Cheesebaron/SentryInitCrash build it in Release mode and deploy to an emulator/device and start the main activity. It will crash on startup with a similar error as above.

Expected Result

SentrySdk.Init should with with AndroidEnableAssemblyCompression = false?

Actual Result

See exceptions above.

@jamescrosswell
Copy link
Collaborator

Hey @Cheesebaron,

Thanks for raising an issue. I'd avoid setting IsGlobalModeEnabled = false in UI applications. That would cause all kinds of issues (it causes scopes, transactions and breadcrumbs etc. to have an affinity for async contexts - that makes sense for HTTP requests in an ASP.NET apps but not for Android or MAUI apps).

The original problem you're seeing appears to be coming from here:

var directoryPath = Path.Combine(rootPath, "Sentry", options.Dsn!.GetHashString());

var hash = sha.ComputeHash(bytes);

Seemingly that ComputeHash method fails on your target platform. It's weird that it complains about concurrent use, since the whole thing is wrapped in a lock:

The good news is that I can reproduce with the sample app you provided! And I've found a couple of clues on stack overflow so it should be possible to find a way to work around this.

@Cheesebaron
Copy link
Contributor Author

I am not even sure why it is only an issue when AndroidEnableAssemblyCompression in csproj is to false. Almost inclined to say it is an issue in the .NET workload.

The Global Mode seems to be a misunderstanding from my colleague when setting up Sentry in that App, will let them know 🤔

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 27, 2025
@jamescrosswell
Copy link
Collaborator

jamescrosswell commented Jan 28, 2025

Interestingly, I don't get the problem with the following changes:

- var options = new SentryLoggingOptions
+ var options = new SentryOptions
   {
-       Dsn = "https://[email protected]/5428537",
+       Dsn = "https://[email protected]/5428537"
-       MinimumEventLevel = LogLevel.Critical
   };
   SentrySdk.Init(options);

This is odd since the SentryLoggingOptions aren't used in any call to AddSentry to initialise the MEL integration in the minimal repro app... so I wouldn't expect this to have any impact on the SDK initialisation (the extra properties in SentryLoggingOptions should just be ignored when calling SentrySdk.Init).

@Cheesebaron is there a reason why you're using SentryLoggingOptions rather than SentryOptions in the call to Init?

@Cheesebaron
Copy link
Contributor Author

@Cheesebaron is there a reason why you're using SentryLoggingOptions rather than SentryOptions in the call to Init?

Sure, in this sample it probably doesn't make sense. The code was extracted from an App where we also call AddSentry on a ServiceCollection to get logs as breadcrumbs, and my colleague who set it up was probably under the impression they needed to use SentryLoggingOptions, will go through how it is set up today to make sure we are doing the correct thing :)

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 28, 2025
@pkubs-ui
Copy link

This is odd since the SentryLoggingOptions aren't used in any call to AddSentry to initialise the MEL integration in the minimal repro app... so I wouldn't expect this to have any impact on the SDK initialisation (the extra properties in SentryLoggingOptions should just be ignored when calling SentrySdk.Init).

I have the same issue as Cheesebaron. Had originally SentrySdk.Init(o => { //... }); and have tried with passing SentryOptions to SentrySdk.Init. Is a not a MAUI project but a .net for Android project running net9 with Sentry sdk 5.0.1.

With AndroidEnableAssemblyCompression=True it works.

Options:

  Dsn = "<dns>",
  AutoSessionTracking = true,
  Environment = "<env>",
  SampleRate = 1.0f,
  CaptureFailedRequests = false,
  Release = "<buildNo>",
#if ANDROID
  Native.EnableNdk = true;
#endif

It's not the same Exception msg, similar though

[ERROR] FATAL UNHANDLED EXCEPTION: 
System.Security.Cryptography.CryptographicException: Concurrent operations from multiple threads on this type are not supported.
    at System.Security.Cryptography.ConcurrencyBlock.Enter(ConcurrencyBlock& block)
    at System.Security.Cryptography.HashProviderDispenser.EvpHashProvider.FinalizeHashAndReset(Span`1 destination)
    at System.Security.Cryptography.HashProvider.FinalizeHashAndReset()
    at System.Security.Cryptography.SHA1.Implementation.HashFinal()
    at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize()
    at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer)
    at Sentry.Internal.Extensions.HashExtensions.GetHashString(String str, Boolean upperCase)
    at Sentry.Internal.InstallationIdHelper.TryGetPersistentInstallationId()
    at Sentry.Internal.InstallationIdHelper.TryGetInstallationId()
    at Sentry.SentryOptions.<.ctor>b__346_0()
    at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral]].ViaFactory(LazyThreadSafetyMode mode)
    at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral]].ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
    at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral]].CreateValue()
    at System.Lazy`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral]].get_Value()
    at Sentry.SentryOptions.get_InstallationId()
    at Sentry.GlobalSessionManager.StartSession()
    at Sentry.Internal.Hub.StartSession()
    at Sentry.Integrations.AutoSessionTrackingIntegration.Register(IHub hub, SentryOptions options)
    at Sentry.Internal.Hub..ctor(SentryOptions options, ISentryClient client, ISessionManager sessionManager, ISystemClock clock, IInternalScopeManager scopeManager, RandomValuesFactory randomValuesFactory)
    at Sentry.SentrySdk.InitHub(SentryOptions options)
    at Sentry.SentrySdk.Init(SentryOptions options)
    at Sentry.SentrySdk.Init(Action`1 configureOptions)
    ...

@aritchie
Copy link
Collaborator

aritchie commented Feb 4, 2025

This issue is very much in the dotnet internals. I've tried various workarounds without success so far. An issue has been filed with the dotnet android team here: dotnet/android#9752

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blocked Bug Something isn't working Framework: MAUI
Projects
Status: No status
Status: No status
Development

No branches or pull requests

6 participants