Skip to content
Open
9 changes: 2 additions & 7 deletions integration-test/android.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,8 @@ Describe 'MAUI app (<dotnet_version>, <configuration>)' -ForEach $cases -Skip:(-
Dump-ServerErrors -Result $result
$result.HasErrors() | Should -BeFalse
$result.Events() | Should -AnyElementMatch "`"type`":`"System.NullReferenceException`""
# TODO: fix redundant SIGSEGV in Release (#3954)
if ($configuration -eq "Release") {
{ $result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`"" } | Should -Throw
} else {
$result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`""
$result.Events() | Should -HaveCount 1
}
$result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`""
$result.Events() | Should -HaveCount 1
}

It 'Delivers battery breadcrumbs in main thread (<configuration>)' {
Expand Down
1 change: 1 addition & 0 deletions integration-test/net9-maui/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static MauiApp CreateMauiApp()
{
#if ANDROID
options.Dsn = "{{SENTRY_DSN}}";
options.Native.SignalHandlerStrategy = Sentry.Android.SignalHandlerStrategy.ChainAtStart;
#endif
options.Debug = false;
options.DiagnosticLevel = SentryLevel.Error;
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry/Platforms/Android/BindableNativeSentryOptions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Sentry.Android;

// ReSharper disable once CheckNamespace
namespace Sentry;

Expand All @@ -24,6 +26,7 @@ public class NativeOptions
public bool? EnableAutoActivityLifecycleTracing { get; set; }
public bool? EnableActivityLifecycleTracingAutoFinish { get; set; }
public bool? EnableUserInteractionTracing { get; set; }
public SignalHandlerStrategy? SignalHandlerStrategy { get; set; }
public bool? AttachThreads { get; set; }
public TimeSpan? ConnectionTimeout { get; set; }
public bool? EnableNdk { get; set; }
Expand Down Expand Up @@ -66,6 +69,7 @@ public void ApplyTo(SentryOptions.NativeOptions options)
options.EnableAutoActivityLifecycleTracing = EnableAutoActivityLifecycleTracing ?? options.EnableAutoActivityLifecycleTracing;
options.EnableActivityLifecycleTracingAutoFinish = EnableActivityLifecycleTracingAutoFinish ?? options.EnableActivityLifecycleTracingAutoFinish;
options.EnableUserInteractionTracing = EnableUserInteractionTracing ?? options.EnableUserInteractionTracing;
options.SignalHandlerStrategy = SignalHandlerStrategy ?? options.SignalHandlerStrategy;
options.AttachThreads = AttachThreads ?? options.AttachThreads;
options.ConnectionTimeout = ConnectionTimeout ?? options.ConnectionTimeout;
options.EnableNdk = EnableNdk ?? options.EnableNdk;
Expand Down
16 changes: 16 additions & 0 deletions src/Sentry/Platforms/Android/NativeOptions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Sentry.Android;

// ReSharper disable once CheckNamespace
namespace Sentry;

Expand Down Expand Up @@ -152,6 +154,20 @@ internal NativeOptions(SentryOptions options)
/// </remarks>
public bool EnableUserInteractionTracing { get; set; } = false;

/// <summary>
/// Gets or sets the strategy for how Sentry Native's signal handler interacts with the CLR/Mono
/// signal handler.
/// The default value is <see cref="Android.SignalHandlerStrategy.Default"/>.
/// </summary>
/// <remarks>
/// .NET runtimes 10.0.0–10.0.3 (.NET SDKs 10.0.100–10.0.301) are not compatible with
/// <see cref="Android.SignalHandlerStrategy.ChainAtStart"/>. Using it on affected
/// versions throws an <see cref="InvalidOperationException"/> during initialization.
/// The issue was resolved in .NET runtime 10.0.4 (.NET SDK 10.0.400). See
/// <see href="https://github.com/dotnet/runtime/pull/123346">dotnet/runtime#123346</see>.
/// </remarks>
public SignalHandlerStrategy SignalHandlerStrategy { get; set; } = SignalHandlerStrategy.Default;

// ---------- From SentryOptions.java ----------

/// <summary>
Expand Down
15 changes: 14 additions & 1 deletion src/Sentry/Platforms/Android/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,20 @@ private static void InitSentryAndroidSdk(SentryOptions options)
o.ServerName = options.ServerName;
o.SessionTrackingIntervalMillis = (long)options.AutoSessionTrackingInterval.TotalMilliseconds;
o.ShutdownTimeoutMillis = (long)options.ShutdownTimeout.TotalMilliseconds;
o.SetNativeHandlerStrategy(JavaSdk.Android.Core.NdkHandlerStrategy.SentryHandlerStrategyDefault);
var signalHandlerStrategy = options.Native.SignalHandlerStrategy;
if (signalHandlerStrategy == SignalHandlerStrategy.ChainAtStart
&& System.Environment.Version is { Major: 10, Minor: 0, Build: < 4 })
{
var msg = $"SignalHandlerStrategy.ChainAtStart is not compatible with .NET runtime " +
$"{System.Environment.Version}. Update to .NET runtime 10.0.4 or later.";
options.LogFatal(msg);
throw new InvalidOperationException(msg);
}
o.SetNativeHandlerStrategy(signalHandlerStrategy switch
{
SignalHandlerStrategy.ChainAtStart => NdkHandlerStrategy.SentryHandlerStrategyChainAtStart,
_ => NdkHandlerStrategy.SentryHandlerStrategyDefault
});

if (options.CacheDirectoryPath is { } cacheDirectoryPath)
{
Expand Down
29 changes: 29 additions & 0 deletions src/Sentry/Platforms/Android/SignalHandlerStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Sentry.Android;

/// <summary>
/// Defines how Sentry Native's signal handler interacts with the CLR/Mono
/// signal handler.
/// </summary>
public enum SignalHandlerStrategy
{
/// <summary>
/// Sentry Native captures the crash first, then invokes the .NET runtime's signal
/// handler. The runtime may convert the same signal into a managed exception (e.g.,
/// <c>SIGSEGV</c> into <c>NullReferenceException</c>), which can result in duplicate
/// crash reports.
/// </summary>
Default,
/// <summary>
/// Sentry Native invokes the .NET runtime's signal handler first, then captures the
/// native crash. This avoids duplicate crash reports from both the native signal and
/// the managed exception.
/// </summary>
/// <remarks>
/// .NET runtimes 10.0.0–10.0.3 (.NET SDKs 10.0.100–10.0.301) are not compatible with
/// this strategy. Using it on affected versions throws an
/// <see cref="System.InvalidOperationException"/> during initialization.
/// The issue was resolved in .NET runtime 10.0.4 (.NET SDK 10.0.400). See
/// <see href="https://github.com/dotnet/runtime/pull/123346">dotnet/runtime#123346</see>.
/// </remarks>
ChainAtStart
}