Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.ExperimentalOptions.SignalHandlerStrategy = Sentry.Android.SignalHandlerStrategy.ChainAtStart;
#endif
options.Debug = false;
options.DiagnosticLevel = SentryLevel.Error;
Expand Down
7 changes: 7 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 Down Expand Up @@ -40,6 +42,7 @@ public class NativeOptions
internal class NativeExperimentalOptions
{
public NativeSentryReplayOptions SessionReplay { get; set; } = new();
public SignalHandlerStrategy? SignalHandlerStrategy { get; set; }
}

internal class NativeSentryReplayOptions
Expand Down Expand Up @@ -91,6 +94,10 @@ public void ApplyTo(SentryOptions.NativeOptions options)
}
ExperimentalOptions.SessionReplay.RedactAllText = options.ExperimentalOptions.SessionReplay.MaskAllText;
ExperimentalOptions.SessionReplay.RedactAllImages = options.ExperimentalOptions.SessionReplay.MaskAllImages;
if (ExperimentalOptions.SignalHandlerStrategy is { } signalHandlerStrategy)
{
options.ExperimentalOptions.SignalHandlerStrategy = signalHandlerStrategy;
}
}
}
}
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 @@ -264,6 +266,20 @@ public void AddInAppInclude(string prefix)
public class NativeExperimentalOptions
{
public NativeSentryReplayOptions SessionReplay { get; set; } = new();

/// <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.103) are not compatible with
/// <see cref="Android.SignalHandlerStrategy.ChainAtStart"/>. On affected versions,
/// the SDK automatically falls back to <see cref="Android.SignalHandlerStrategy.Default"/>.
/// The issue was resolved in .NET runtime 10.0.4 (.NET SDK 10.0.200). See
/// <see href="https://github.com/dotnet/runtime/pull/123346">dotnet/runtime#123346</see>.
/// </remarks>
public SignalHandlerStrategy SignalHandlerStrategy { get; set; } = SignalHandlerStrategy.Default;
}

public class NativeSentryReplayOptions
Expand Down
17 changes: 16 additions & 1 deletion src/Sentry/Platforms/Android/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,22 @@ 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.ExperimentalOptions.SignalHandlerStrategy;
if (signalHandlerStrategy == SignalHandlerStrategy.ChainAtStart
&& System.Environment.Version is { Major: 10, Minor: 0, Build: < 4 })
{
options.LogWarning(
"SignalHandlerStrategy.ChainAtStart is not compatible with .NET runtime {0}. " +
"Falling back to SignalHandlerStrategy.Default. Update to .NET runtime 10.0.4 or later.",
System.Environment.Version);
signalHandlerStrategy = SignalHandlerStrategy.Default;
}
o.SetNativeHandlerStrategy(signalHandlerStrategy switch
{
SignalHandlerStrategy.ChainAtStart => NdkHandlerStrategy.SentryHandlerStrategyChainAtStart,
_ => NdkHandlerStrategy.SentryHandlerStrategyDefault
});

if (options.CacheDirectoryPath is { } cacheDirectoryPath)
{
Expand Down
31 changes: 31 additions & 0 deletions src/Sentry/Platforms/Android/SignalHandlerStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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. This strategy is supported on Android 8.0 (API level 26)
/// and later; on older versions, Sentry Native silently falls back to
/// <see cref="Default"/>.
/// </summary>
/// <remarks>
/// .NET runtimes 10.0.0–10.0.3 (.NET SDKs 10.0.100–10.0.103) are not compatible with
/// this strategy. On affected versions, the SDK automatically falls back to
/// <see cref="Default"/>. The issue was resolved in .NET runtime 10.0.4
/// (.NET SDK 10.0.200). See
/// <see href="https://github.com/dotnet/runtime/pull/123346">dotnet/runtime#123346</see>.
/// </remarks>
ChainAtStart
}
Loading